我正在用Dave DeLong的極好的CHCSVParser爲Objective-C打造一個非常長的.CSV文件,並且遇到了一些使用它的麻煩。我會使用arrayWithContentsOfCSVFile
方法,但我在iPhone上運行代碼並將整個文件解析到內存中會佔用比可用內存更多的內存。如何使用CHCSVParser類
在我的代碼中,解析器打開文檔並完美地調用委託方法,但委託中的哪些位置會在每行之後停止並訪問數據(以創建Core數據對象並將其保存到數據存儲) ?我認爲這將在- (void) parser:(CHCSVParser *)parser didEndLine:(NSUInteger)lineNumber
中,但是如何在解析器完成該行時獲得NSArray
(或其他)的數據?
這裏是我到目前爲止的代碼:
//
// The code from a method in my view controller:
//
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSFileManager *manager = [NSFileManager defaultManager];
NSError *err = nil;
NSArray *fileList = [manager contentsOfDirectoryAtPath:documentsDirectory error:&err];
NSString *fileName = [fileList objectAtIndex:1];
NSURL *inputFileURL = [NSURL fileURLWithPath: [documentsDirectory stringByAppendingPathComponent:fileName]];
NSStringEncoding encoding = 0;
CHCSVParser *p = [[CHCSVParser alloc] initWithContentsOfCSVFile:[inputFileURL path] usedEncoding:&encoding error:nil];
[p setParserDelegate:self];
[p parse];
[p release];
...
#pragma mark -
#pragma mark CHCSVParserDelegate methods
- (void) parser:(CHCSVParser *)parser didStartDocument:(NSString *)csvFile {
NSLog(@"Parser started!");
}
- (void) parser:(CHCSVParser *)parser didStartLine:(NSUInteger)lineNumber {
//NSLog(@"Parser started line: %i", lineNumber);
}
- (void) parser:(CHCSVParser *)parser didEndLine:(NSUInteger)lineNumber {
NSLog(@"Parser ended line: %i", lineNumber);
}
- (void) parser:(CHCSVParser *)parser didReadField:(NSString *)field {
//NSLog(@"Parser didReadField: %@", field);
}
- (void) parser:(CHCSVParser *)parser didEndDocument:(NSString *)csvFile {
NSLog(@"Parser ended document: %@", csvFile);
}
- (void) parser:(CHCSVParser *)parser didFailWithError:(NSError *)error {
NSLog(@"Parser failed with error: %@ %@", [error localizedDescription], [error userInfo]);
}
謝謝!
感謝您的答案 - 我不知道解析器是否爲您做了這項工作(通過'currentChunk'或其他方式)!不必手動進行聚合就可以了,但對於大多數應用程序而言,CSV解析僅在少數幾個地方用於I/O。如果有人想只寫一點代碼,是否可以子類化或者在CHCSVParserDelegate上寫一個類別? – 2010-09-24 18:41:57
@Neal'CHCSVParserDelegate'是一個協議,所以你不能繼承它。爲了使這種行爲發揮作用,你必須直接改變'CHCSVParser'或者對其進行子類化。最簡單的答案是自己總結線路(就像我在答案中一樣) – 2010-09-24 18:45:44
不這麼認爲......非常感謝這裏的精彩工作!實際上,對你的代碼進行小幅更正......在'didEndLine'中,我們需要將'currentLine'改爲'currentRow'。 (我會改變它,但沒有足夠的XP;)) – 2010-09-24 18:50:02