Ios一行一行讀取大檔案

來源:互聯網
上載者:User
 
//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//DDFileReader.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@endIf your file is small, then @mipadi's method will probably be just fine. However, if your file is large (> 1MB, perhaps?), then you may want to consider reading the file line-by-line. I wrote a class once to do that, which I'll paste here://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//DDFileReader.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

 

Then to use this, you'd do:

 
DDFileReader * reader = [[DDFileReader alloc] initWithFilePath:pathToMyFile];NSString * line = nil;while ((line = [reader readLine])) {  NSLog(@"read line: %@", line);}[reader release];Or (for 10.6+ and iOS 4+):DDFileReader * reader = [[DDFileReader alloc] initWithFilePath:pathToMyFile];[reader enumerateLinesUsingBlock:^(NSString * line, BOOL * stop) {  NSLog(@"read line: %@", line);}];[reader release];



http://stackoverflow.com/questions/3707427/how-to-read-data-from-nsfilehandle-line-by-line?lq=1

 
 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.