sourcetip

목표-C: 파일을 한 줄씩 읽기

fileupload 2023. 4. 28. 21:15
반응형

목표-C: 파일을 한 줄씩 읽기

목표-C에서 대용량 텍스트 파일을 처리하는 적절한 방법은 무엇입니까?각 행을 개별적으로 읽고 각 행을 NSS 문자열로 처리하려고 합니다.이것을 하는 가장 효율적인 방법은 무엇입니까?

한 가지 솔루션은 NSString 방법을 사용하는 것입니다.

+ (id)stringWithContentsOfFile:(NSString *)path 
      encoding:(NSStringEncoding)enc 
      error:(NSError **)error 

그런 다음 새 줄 구분 기호를 사용하여 줄을 나눈 다음 배열의 요소 위에 반복합니다.하지만, 이것은 상당히 비효율적으로 보입니다.파일을 한 번에 모두 읽는 대신 각 줄에 열거하는 스트림으로 취급하는 쉬운 방법이 없을까요?자바의 java.io 같은 것입니다.버퍼링된 독서자입니다.

이것은 일반적인 판독에 사용됩니다.StringText긴 텍스트(큰 텍스트 크기)를 읽으려면 버퍼링(메모리 공간에서 텍스트 크기 예약)과 같은 다른 사용자가 언급한 방법을 사용합니다.

텍스트 파일을 읽었다고 가정합니다.

NSString* filePath = @""//file path...
NSString* fileRoot = [[NSBundle mainBundle] 
               pathForResource:filePath ofType:@"txt"];

당신은 새로운 라인을 없애고 싶어합니다.

// read everything from text
NSString* fileContents = 
      [NSString stringWithContentsOfFile:fileRoot 
       encoding:NSUTF8StringEncoding error:nil];

// first, separate by new line
NSArray* allLinedStrings = 
      [fileContents componentsSeparatedByCharactersInSet:
      [NSCharacterSet newlineCharacterSet]];

// then break down even further 
NSString* strsInOneLine = 
      [allLinedStrings objectAtIndex:0];

// choose whatever input identity you have decided. in this case ;
NSArray* singleStrs = 
      [currentPointString componentsSeparatedByCharactersInSet:
      [NSCharacterSet characterSetWithCharactersInString:@";"]];

바로 그겁니다.

좋은 질문입니다.는 @Dederik이 좋은 답을 가지고 있다고 생각하지만, 코코아가 여러분이 정확히 무엇을 하고 싶은지에 대한 메커니즘을 가지고 있지 않다는 것은 유감스러운 일입니다.

NSInputStream N바이트의 청크를 읽을 수 있습니다(와 매우 유사함)java.io.BufferedReader)로, , , 로 NSString직접 새 줄(또는 다른 구분 기호)을 스캔하여 다음 읽기에 사용할 나머지 문자를 저장하거나 새 줄을 아직 읽지 않은 경우 더 많은 문자를 읽습니다.NSFileHandleNSData 그면당그은변수있환다니습할것을신러▁an다▁to▁you니▁which로 변환할 수 .NSString하지만 본질적으로 같은 과정입니다.)

Apple에는 세부 정보를 작성하는 데 도움이 될 수 있는 스트림 프로그래밍 가이드가 있으며, 이 SO 질문은 귀하가 처리할 경우에도 도움이 될 수 있습니다.uint8_t*완충 장치

에서) 와 같은 을 위해 할 수 로 분류할 수 있는 수업에서 이 동작을 캡슐화하는 것이 좋을 것입니다.NSInputStream하위 분류되도록 설계됨) 및 원하는 내용을 정확하게 읽을 수 있는 방법을 추가합니다.

참고로, 저는 이것이 추가하기에 좋은 기능이라고 생각하며, 이것을 가능하게 하는 것에 대해 개선 요청을 할 것입니다. :-)


편집: 이 요청이 이미 존재합니다.2006년부터 시작된 레이더가 있습니다(애플 내부 사용자의 경우 rdar://4742914).

이렇게 하면 효과가 있습니다.

#include <stdio.h>

NSString *readLineAsNSString(FILE *file)
{
    char buffer[4096];

    // tune this capacity to your liking -- larger buffer sizes will be faster, but
    // use more memory
    NSMutableString *result = [NSMutableString stringWithCapacity:256];

    // Read up to 4095 non-newline characters, then read and discard the newline
    int charsRead;
    do
    {
        if(fscanf(file, "%4095[^\n]%n%*c", buffer, &charsRead) == 1)
            [result appendFormat:@"%s", buffer];
        else
            break;
    } while(charsRead == 4095);

    return result;
}

다음과 같이 사용합니다.

FILE *file = fopen("myfile", "r");
// check for NULL
while(!feof(file))
{
    NSString *line = readLineAsNSString(file);
    // do stuff with line; line is autoreleased, so you should NOT release it (unless you also retain it beforehand)
}
fclose(file);

이 코드는 파일에서 한 번에 최대 4095개의 줄 바꿈 문자를 읽습니다.4095자보다 긴 줄이 있는 경우 새 줄이나 파일 끝에 도달할 때까지 계속 읽습니다.

참고: 이 코드는 테스트하지 않았습니다.사용하기 전에 테스트하십시오.

Unix, 는 C이므로 오래된 Mac OS X-X Unix, Objective-C C를 .fopen그리고.fgets<stdio.h>그것은 작동할 것이 보장됩니다.

[NSString stringWithUTF8String:buf]을 C 자열을다변음환다니합로로 합니다.NSString다른 인코딩에서 문자열을 만들고 복사하지 않고 만드는 방법도 있습니다.

사용할 수 있습니다.NSInputStream파일 스트림에 대한 기본 구현이 있습니다. 수 .read:maxLength:방법)을 선택합니다.버퍼에서 새 줄을 직접 스캔해야 합니다.

Cocoa/Objective-C에서 텍스트 파일을 읽는 적절한 방법은 Apple의 String 프로그래밍 가이드에 설명되어 있습니다.파일 읽기쓰기 섹션은 원하는 항목이어야 합니다.PS: "라인"이 뭐죠?"\n"으로 구분된 문자열의 두 부분?아니면 "\r"?아니면 "\r\n"?아니면 당신이 실제로 문단을 찾고 있는지도?앞에서 설명한 안내서에는 문자열을 줄이나 단락으로 나누는 것에 대한 섹션도 포함되어 있습니다. (이 섹션은 "단락 및 줄 바꿈"이라고 하며, 위에서 가리킨 페이지의 왼쪽 메뉴에서 에 연결되어 있습니다.안타깝게도 제가 아직 신뢰할 수 있는 사용자가 아니기 때문에 이 사이트에서는 두 개 이상의 URL을 게시할 수 없습니다.)

Knuth의 말을 빌리자면, 조기 최적화는 모든 악의 근원입니다.단순히 "전체 파일을 메모리로 읽는 것"이 느리다고 가정하지 마십시오.당신은 그것을 벤치마킹했습니까?당신은 그것이 실제로 전체 파일을 메모리에 읽는다는 것을 알고 있습니까?아마도 단순히 프록시 객체를 반환하고 문자열을 사용하면서 백그라운드에서 계속 읽는 것이 아닐까요? (거부자: NSString이 실제로 이런 일을 하는지 모르겠습니다. 그럴 수도 있습니다.)요점은: 먼저 문서화된 방식으로 일을 진행하는 것입니다.그런 다음 벤치마크에서 원하는 성능이 아닌 것으로 나타나면 최적화합니다.

이러한 답변의 대부분은 긴 코드 덩어리이거나 전체 파일에서 읽습니다.저는 바로 이 작업에 c 방법을 사용하는 것을 좋아합니다.

FILE* file = fopen("path to my file", "r");

size_t length;
char *cLine = fgetln(file,&length);

while (length>0) {
    char str[length+1];
    strncpy(str, cLine, length);
    str[length] = '\0';

    NSString *line = [NSString stringWithFormat:@"%s",str];        
    % Do what you want here.

    cLine = fgetln(file,&length);
}

fgetln은 새 줄 문자를 유지하지 않습니다.또한 NULL 종단을 위한 공간을 만들고자 하기 때문에 Str의 길이를 +1로 합니다.

@porneL이 말했듯이, Capi는 매우 유용합니다.

NSString* fileRoot = [[NSBundle mainBundle] pathForResource:@"record" ofType:@"txt"];
FILE *file = fopen([fileRoot UTF8String], "r");
char buffer[256];
while (fgets(buffer, 256, file) != NULL){
    NSString* result = [NSString stringWithUTF8String:buffer];
    NSLog(@"%@",result);
}

파일을 한 줄씩 읽으려면(극히 큰 파일의 경우에도) 다음 기능을 사용할 수 있습니다.

DDFileReader * reader = [[DDFileReader alloc] initWithFilePath:pathToMyFile];
NSString * line = nil;
while ((line = [reader readLine])) {
  NSLog(@"read line: %@", line);
}
[reader release];

또는:

DDFileReader * reader = [[DDFileReader alloc] initWithFilePath:pathToMyFile];
[reader enumerateLinesUsingBlock:^(NSString * line, BOOL * stop) {
  NSLog(@"read line: %@", line);
}];
[reader release];

이를 활성화하는 클래스 DDFileReader는 다음과 같습니다.

인터페이스 파일(.h):

@interface DDFileReader : NSObject {
    NSString * filePath;

    NSFileHandle * fileHandle;
    unsigned long long currentOffset;
    unsigned long long totalFileLength;

    NSString * lineDelimiter;
    NSUInteger chunkSize;
}

@property (nonatomic, copy) NSString * lineDelimiter;
@property (nonatomic) NSUInteger chunkSize;

- (id) initWithFilePath:(NSString *)aPath;

- (NSString *) readLine;
- (NSString *) readTrimmedLine;

#if NS_BLOCKS_AVAILABLE
- (void) enumerateLinesUsingBlock:(void(^)(NSString*, BOOL *))block;
#endif

@end

구현(.m)

#import "DDFileReader.h"

@interface NSData (DDAdditions)

- (NSRange) rangeOfData_dd:(NSData *)dataToFind;

@end

@implementation NSData (DDAdditions)

- (NSRange) rangeOfData_dd:(NSData *)dataToFind {

    const void * bytes = [self bytes];
    NSUInteger length = [self length];

    const void * searchBytes = [dataToFind bytes];
    NSUInteger searchLength = [dataToFind length];
    NSUInteger searchIndex = 0;

    NSRange foundRange = {NSNotFound, searchLength};
    for (NSUInteger index = 0; index < length; index++) {
        if (((char *)bytes)[index] == ((char *)searchBytes)[searchIndex]) {
            //the current character matches
            if (foundRange.location == NSNotFound) {
                foundRange.location = index;
            }
            searchIndex++;
            if (searchIndex >= searchLength) { return foundRange; }
        } else {
            searchIndex = 0;
            foundRange.location = NSNotFound;
        }
    }
    return foundRange;
}

@end

@implementation DDFileReader
@synthesize lineDelimiter, chunkSize;

- (id) initWithFilePath:(NSString *)aPath {
    if (self = [super init]) {
        fileHandle = [NSFileHandle fileHandleForReadingAtPath:aPath];
        if (fileHandle == nil) {
            [self release]; return nil;
        }

        lineDelimiter = [[NSString alloc] initWithString:@"\n"];
        [fileHandle retain];
        filePath = [aPath retain];
        currentOffset = 0ULL;
        chunkSize = 10;
        [fileHandle seekToEndOfFile];
        totalFileLength = [fileHandle offsetInFile];
        //we don't need to seek back, since readLine will do that.
    }
    return self;
}

- (void) dealloc {
    [fileHandle closeFile];
    [fileHandle release], fileHandle = nil;
    [filePath release], filePath = nil;
    [lineDelimiter release], lineDelimiter = nil;
    currentOffset = 0ULL;
    [super dealloc];
}

- (NSString *) readLine {
    if (currentOffset >= totalFileLength) { return nil; }

    NSData * newLineData = [lineDelimiter dataUsingEncoding:NSUTF8StringEncoding];
    [fileHandle seekToFileOffset:currentOffset];
    NSMutableData * currentData = [[NSMutableData alloc] init];
    BOOL shouldReadMore = YES;

    NSAutoreleasePool * readPool = [[NSAutoreleasePool alloc] init];
    while (shouldReadMore) {
        if (currentOffset >= totalFileLength) { break; }
        NSData * chunk = [fileHandle readDataOfLength:chunkSize];
        NSRange newLineRange = [chunk rangeOfData_dd:newLineData];
        if (newLineRange.location != NSNotFound) {

            //include the length so we can include the delimiter in the string
            chunk = [chunk subdataWithRange:NSMakeRange(0, newLineRange.location+[newLineData length])];
            shouldReadMore = NO;
        }
        [currentData appendData:chunk];
        currentOffset += [chunk length];
    }
    [readPool release];

    NSString * line = [[NSString alloc] initWithData:currentData encoding:NSUTF8StringEncoding];
    [currentData release];
    return [line autorelease];
}

- (NSString *) readTrimmedLine {
    return [[self readLine] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}

#if NS_BLOCKS_AVAILABLE
- (void) enumerateLinesUsingBlock:(void(^)(NSString*, BOOL*))block {
  NSString * line = nil;
  BOOL stop = NO;
  while (stop == NO && (line = [self readLine])) {
    block(line, &stop);
  }
}
#endif

@end

그 수업은 Dave DeLong에 의해 행해졌습니다.

다른 사람들이 대답했듯이 NSInputStream과 NSFileHandle은 모두 좋은 옵션이지만 NSData와 메모리 매핑을 사용하여 상당히 작은 방식으로 수행할 수도 있습니다.

BRLin Reader.h

#import <Foundation/Foundation.h>

@interface BRLineReader : NSObject

@property (readonly, nonatomic) NSData *data;
@property (readonly, nonatomic) NSUInteger linesRead;
@property (strong, nonatomic) NSCharacterSet *lineTrimCharacters;
@property (readonly, nonatomic) NSStringEncoding stringEncoding;

- (instancetype)initWithFile:(NSString *)filePath encoding:(NSStringEncoding)encoding;
- (instancetype)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding;
- (NSString *)readLine;
- (NSString *)readTrimmedLine;
- (void)setLineSearchPosition:(NSUInteger)position;

@end

BRLin Reader.m

#import "BRLineReader.h"

static unsigned char const BRLineReaderDelimiter = '\n';

@implementation BRLineReader
{
    NSRange _lastRange;
}

- (instancetype)initWithFile:(NSString *)filePath encoding:(NSStringEncoding)encoding
{
    self = [super init];
    if (self) {
        NSError *error = nil;
        _data = [NSData dataWithContentsOfFile:filePath options:NSDataReadingMappedAlways error:&error];
        if (!_data) {
            NSLog(@"%@", [error localizedDescription]);
        }
        _stringEncoding = encoding;
        _lineTrimCharacters = [NSCharacterSet whitespaceAndNewlineCharacterSet];
    }

    return self;
}

- (instancetype)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding
{
    self = [super init];
    if (self) {
        _data = data;
        _stringEncoding = encoding;
        _lineTrimCharacters = [NSCharacterSet whitespaceAndNewlineCharacterSet];
    }

    return self;
}

- (NSString *)readLine
{
    NSUInteger dataLength = [_data length];
    NSUInteger beginPos = _lastRange.location + _lastRange.length;
    NSUInteger endPos = 0;
    if (beginPos == dataLength) {
        // End of file
        return nil;
    }

    unsigned char *buffer = (unsigned char *)[_data bytes];
    for (NSUInteger i = beginPos; i < dataLength; i++) {
        endPos = i;
        if (buffer[i] == BRLineReaderDelimiter) break;
    }

    // End of line found
    _lastRange = NSMakeRange(beginPos, endPos - beginPos + 1);
    NSData *lineData = [_data subdataWithRange:_lastRange];
    NSString *line = [[NSString alloc] initWithData:lineData encoding:_stringEncoding];
    _linesRead++;

    return line;
}

- (NSString *)readTrimmedLine
{
    return [[self readLine] stringByTrimmingCharactersInSet:_lineTrimCharacters];
}

- (void)setLineSearchPosition:(NSUInteger)position
{
    _lastRange = NSMakeRange(position, 0);
    _linesRead = 0;
}

@end

이 대답은 ObjC가 아니라 C입니다.

ObjC는 'C' 기반이므로 페젯을 사용하면 어떨까요?

그리고 네, ObjC만의 방법이 있다고 확신합니다 - 저는 아직 그것이 무엇인지 알 만큼 능숙하지 않습니다 :)

@ 아담로대의답서, 포맷문열자의 형식 입니다.fscanf아래와 같이 변경됩니다.

"%4095[^\r\n]%n%*[\n\r]"

OSx, 리눅스, 윈도우 라인 엔드에서 작동할 것입니다.

카테고리 또는 확장 기능을 사용하여 우리의 삶을 조금 더 쉽게 만듭니다.

extension String {

    func lines() -> [String] {
        var lines = [String]()
        self.enumerateLines { (line, stop) -> () in
            lines.append(line)
        }
        return lines
    }

}

// then
for line in string.lines() {
    // do the right thing
}

저는 @lukaswelte의 응답과 Dave DeLong의 코드가 매우 도움이 된다는 것을 알았습니다.이 문제에 대한 해결책을 찾고 있었지만 대용량 파일을 구문 분석해야 했습니다.\r\n뿐만 아니라.\n.

작성된 코드에 둘 이상의 문자로 구문 분석하는 경우 버그가 포함되어 있습니다.코드를 아래와 같이 변경하였습니다.

.h 파일:

#import <Foundation/Foundation.h>

@interface FileChunkReader : NSObject {
    NSString * filePath;

    NSFileHandle * fileHandle;
    unsigned long long currentOffset;
    unsigned long long totalFileLength;

    NSString * lineDelimiter;
    NSUInteger chunkSize;
}

@property (nonatomic, copy) NSString * lineDelimiter;
@property (nonatomic) NSUInteger chunkSize;

- (id) initWithFilePath:(NSString *)aPath;

- (NSString *) readLine;
- (NSString *) readTrimmedLine;

#if NS_BLOCKS_AVAILABLE
- (void) enumerateLinesUsingBlock:(void(^)(NSString*, BOOL *))block;
#endif

@end

.m 파일:

#import "FileChunkReader.h"

@interface NSData (DDAdditions)

- (NSRange) rangeOfData_dd:(NSData *)dataToFind;

@end

@implementation NSData (DDAdditions)

- (NSRange) rangeOfData_dd:(NSData *)dataToFind {

    const void * bytes = [self bytes];
    NSUInteger length = [self length];

    const void * searchBytes = [dataToFind bytes];
    NSUInteger searchLength = [dataToFind length];
    NSUInteger searchIndex = 0;

    NSRange foundRange = {NSNotFound, searchLength};
    for (NSUInteger index = 0; index < length; index++) {
        if (((char *)bytes)[index] == ((char *)searchBytes)[searchIndex]) {
            //the current character matches
            if (foundRange.location == NSNotFound) {
                foundRange.location = index;
            }
            searchIndex++;
            if (searchIndex >= searchLength)
            {
                return foundRange;
            }
        } else {
            searchIndex = 0;
            foundRange.location = NSNotFound;
        }
    }

    if (foundRange.location != NSNotFound
        && length < foundRange.location + foundRange.length )
    {
        // if the dataToFind is partially found at the end of [self bytes],
        // then the loop above would end, and indicate the dataToFind is found
        // when it only partially was.
        foundRange.location = NSNotFound;
    }

    return foundRange;
}

@end

@implementation FileChunkReader

@synthesize lineDelimiter, chunkSize;

- (id) initWithFilePath:(NSString *)aPath {
    if (self = [super init]) {
        fileHandle = [NSFileHandle fileHandleForReadingAtPath:aPath];
        if (fileHandle == nil) {
            return nil;
        }

        lineDelimiter = @"\n";
        currentOffset = 0ULL; // ???
        chunkSize = 128;
        [fileHandle seekToEndOfFile];
        totalFileLength = [fileHandle offsetInFile];
        //we don't need to seek back, since readLine will do that.
    }
    return self;
}

- (void) dealloc {
    [fileHandle closeFile];
    currentOffset = 0ULL;

}

- (NSString *) readLine {
    if (currentOffset >= totalFileLength)
    {
        return nil;
    }

    @autoreleasepool {

        NSData * newLineData = [lineDelimiter dataUsingEncoding:NSUTF8StringEncoding];
        [fileHandle seekToFileOffset:currentOffset];
        unsigned long long originalOffset = currentOffset;
        NSMutableData *currentData = [[NSMutableData alloc] init];
        NSData *currentLine = [[NSData alloc] init];
        BOOL shouldReadMore = YES;


        while (shouldReadMore) {
            if (currentOffset >= totalFileLength)
            {
                break;
            }

            NSData * chunk = [fileHandle readDataOfLength:chunkSize];
            [currentData appendData:chunk];

            NSRange newLineRange = [currentData rangeOfData_dd:newLineData];

            if (newLineRange.location != NSNotFound) {

                currentOffset = originalOffset + newLineRange.location + newLineData.length;
                currentLine = [currentData subdataWithRange:NSMakeRange(0, newLineRange.location)];

                shouldReadMore = NO;
            }else{
                currentOffset += [chunk length];
            }
        }

        if (currentLine.length == 0 && currentData.length > 0)
        {
            currentLine = currentData;
        }

        return [[NSString alloc] initWithData:currentLine encoding:NSUTF8StringEncoding];
    }
}

- (NSString *) readTrimmedLine {
    return [[self readLine] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}

#if NS_BLOCKS_AVAILABLE
- (void) enumerateLinesUsingBlock:(void(^)(NSString*, BOOL*))block {
    NSString * line = nil;
    BOOL stop = NO;
    while (stop == NO && (line = [self readLine])) {
        block(line, &stop);
    }
}
#endif

@end

제가 시도한 다른 모든 답변들이 이러쿵저러쿵 부족했기 때문에 이것을 추가합니다.다음 방법은 큰 파일, 임의의 긴 줄 및 빈 줄을 처리할 수 있습니다.실제 콘텐츠로 테스트되었으며 출력에서 새 줄 문자를 제거합니다.

- (NSString*)readLineFromFile:(FILE *)file
{
    char buffer[4096];
    NSMutableString *result = [NSMutableString stringWithCapacity:1000];

    int charsRead;
    do {
        if(fscanf(file, "%4095[^\r\n]%n%*[\n\r]", buffer, &charsRead) == 1) {
            [result appendFormat:@"%s", buffer];
        }
        else {
            break;
        }
    } while(charsRead == 4095);

    return result.length ? result : nil;
}

크레딧은 @Adam Rosenfield와 @sooop에게 전달됩니다.

이러한 답변의 대부분은 텍스트 파일을 한 번에 한 덩어리씩 메모리에 저장하는 대신 전체 텍스트 파일을 읽는 데 의존합니다.FileHandle을 사용하여 메모리 영향을 낮게 유지하는 최신 Swift의 솔루션은 다음과 같습니다.

enum MyError {
    case invalidTextFormat
}

extension FileHandle {

    func readLine(maxLength: Int) throws -> String {

        // Read in a string of up to the maximum length
        let offset = offsetInFile
        let data = readData(ofLength: maxLength)
        guard let string = String(data: data, encoding: .utf8) else {
            throw MyError.invalidTextFormat
        }

        // Check for carriage returns; if none, this is the whole string
        let substring: String
        if let subindex = string.firstIndex(of: "\n") {
            substring = String(string[string.startIndex ... subindex])
        } else {
            substring = string
        }

        // Wind back to the correct offset so that we don't miss any lines
        guard let dataCount = substring.data(using: .utf8, allowLossyConversion: false)?.count else {
            throw MyError.invalidTextFormat
        }
        try seek(toOffset: offset + UInt64(dataCount))
        return substring
    }

}

이렇게 하면 라인 끝에 캐리지 리턴이 유지되므로 필요에 따라 코드를 조정하여 캐리지 리턴을 제거할 수 있습니다.

용도: 대상 텍스트 파일에 대한 파일 핸들을 열고 호출하기만 하면 됩니다.readLine적절한 최대 길이 - 1024는 일반 텍스트의 표준이지만, 더 짧을 것이라는 것을 알 수 있도록 열어 두었습니다.명령어는 파일의 끝을 오버플로하지 않으므로 전체를 구문 분석하려면 파일에 도달하지 않았는지 수동으로 확인해야 할 수도 있습니다.다음은 파일을 여는 방법을 보여주는 몇 가지 샘플 코드입니다.myFileURL끝까지 한 줄 한 줄 읽으세요.

do {
    let handle = try FileHandle(forReadingFrom: myFileURL)
    try handle.seekToEndOfFile()
    let eof = handle.offsetInFile
    try handle.seek(toFileOffset: 0)

    while handle.offsetInFile < eof {
        let line = try handle.readLine(maxLength: 1024)
        // Do something with the string here
    }
    try handle.close()
catch let error {
    print("Error reading file: \(error.localizedDescription)"
}

소규모 파일에 사용할 수 있는 편리한 솔루션은 다음과 같습니다.

NSString *path = [[NSBundle mainBundle] pathForResource:@"Terrain1" ofType:@"txt"];
NSString *contents = [NSString stringWithContentsOfFile:path encoding:NSASCIIStringEncoding error:nil];
NSArray *lines = [contents componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\r\n"]];
for (NSString* line in lines) {
    if (line.length) {
        NSLog(@"line: %@", line);
    }
}

이 스크립트를 사용하면 효과적입니다.

NSString *path = @"/Users/xxx/Desktop/names.txt";
NSError *error;
NSString *stringFromFileAtPath = [NSString stringWithContentsOfFile: path
                                                           encoding: NSUTF8StringEncoding
                                                              error: &error];
if (stringFromFileAtPath == nil) {
    NSLog(@"Error reading file at %@\n%@", path, [error localizedFailureReason]);
}
NSLog(@"Contents:%@", stringFromFileAtPath);

언급URL : https://stackoverflow.com/questions/1044334/objective-c-reading-a-file-line-by-line

반응형