//
// TTDFileReader.m
// TestTagDemo
//
// Created by 段弘 on 14-1-2.
// Copyright (c) 2014年 百度. All rights reserved.
//
#import "TTDFileReader.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 TTDFileReader
@synthesize lineDelimiter, chunkSize;
- (id) initWithFilePath:(NSString *)aPath {
if (self = [super init]) {
fileHandle = [NSFileHandle fileHandleForReadingAtPath:aPath];
if (fileHandle == nil) {
NSLog(@"fileHandle is nil!");
return nil;
}
lineDelimiter = @"\n";
filePath = aPath;
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 = nil;
filePath = nil;
lineDelimiter = nil;
currentOffset = 0ULL;
}
- (NSString *) readLineWithEncoding:(NSStringEncoding)encoding {
if (currentOffset >= totalFileLength) { return nil; }
NSData * newLineData = [lineDelimiter dataUsingEncoding:encoding];
[fileHandle seekToFileOffset:currentOffset];
NSMutableData * currentData = [[NSMutableData alloc] init];
BOOL shouldReadMore = YES;
@autoreleasepool{
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];
}
}
NSString * line = [[NSString alloc] initWithData:currentData encoding:encoding];
return line;
}
- (NSString *) readTrimmedLineWithEncoding:(NSStringEncoding)encoding {
return [[self readLineWithEncoding:encoding] stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
}
@end