如何使用CHCSVParser类 [英] How To Use the CHCSVParser class

查看:272
本文介绍了如何使用CHCSVParser类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在和Dave DeLong一起玩Objective-C的极好的 CHCSVParser ,使用非常长的.CSV文件和我遇到一些麻烦使用它。我将使用 arrayWithContentsOfCSVFile 方法,但是我在iPhone上运行代码,并将整个文件解析到内存将需要比可用的更多的内存。

I am playing around with Dave DeLong's excellent CHCSVParser for Objective-C with an extremely long .CSV file and am running into some trouble using it. I would use the arrayWithContentsOfCSVFile method, but I'm running the code on an iPhone and parsing the whole file into memory would take more memory than is available.

在下面的代码中,解析器打开文档并完全调用委托方法,但在代理中,我在每行之后停止并访问数据(创建和保存Core Data对象到数据存储)?我假设在 - (void)parser:(CHCSVParser *)parser didEndLine:(NSUInteger)lineNumber ,但是如何获得 NSArray

In my code below, the parser opens the document and calls the delegate methods perfectly, but where in the delegate do I stop after each line and access the data (to create and save a Core Data object to the data store)? I assume that would be in - (void) parser:(CHCSVParser *)parser didEndLine:(NSUInteger)lineNumber, but how do I get an NSArray (or whatever) of the data from the parser when it's done with the line?

到目前为止,我的代码是

Here is my code so far:

//
// 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]);
}

谢谢!

推荐答案

我很高兴看到我的代码证明是有用的! :)

I'm glad to see that my code is proving useful! :)

CHCSVParser 的行为类似于 NSXMLParser ,因为每次它发现一些有趣的东西,它会让你知道通过一个委托回调。然而,如果你选择忽略它给你在回调中的数据,那么它已经走了。这些解析器( CHCSVParser NSXMLParser )非常愚蠢。他们只知道他们想要解析的东西的格式,但是真正做的不是那么多。

CHCSVParser is similar in behavior to an NSXMLParser, in that every time it finds something interesting, it's going to let you know via one of the delegate callbacks. However, if you choose to ignore the data that it gives you in the callback, then it's gone. These parsers (CHCSVParser and NSXMLParser) are pretty stupid. They just know the format of the stuff they're trying to parse, but don't really do much beyond that.

所以,简而言之,答案是你必须自己保存。如果你查看 NSArray 类别的代码,你会在.m文件中看到它使用一个简单的 NSObject 子类作为解析器委托,是什么将字段聚合成一个数组,然后将该数组添加到整个数组。

So the answer, in a nutshell, is "you have to save it yourself". If you look at the code for the NSArray category, you'll see in the .m file that it's using a simple NSObject subclass as the parser delegate, and that subclass is what's aggregating the fields into an array, and then adding that array to the overall array. You'll need to do something similar.

示例委托:

@interface CSVParserDelegate : NSObject <CHCSVParserDelegate> {
  NSMutableArray * currentRow;
}
@end

@implementation CSVParserDelegate

- (void) parser:(CHCSVParser *)parser didStartLine:(NSUInteger)lineNumber {
  currentRow = [[NSMutableArray alloc] init];
}
- (void) parser:(CHCSVParser *)parser didReadField:(NSString *)field {
  [currentRow addObject:field];
}
- (void) parser:(CHCSVParser *)parser didEndLine:(NSUInteger)lineNumber {
  NSLog(@"finished line! %@", currentRow);
  [self doSomethingWithLine:currentRow];
  [currentRow release], currentRow = nil;
}
@end

但是,我可以说服修改行为解析器聚合行本身,但如果我走下那条路线,为什么不让解析器聚合整个文件? (答案:不应该)

However, I could be convinced to modify the behavior of the parser to aggregate the row itself, but if I go down that route, why not just have the parser aggregate the entire file? (Answer: it shouldn't)

这篇关于如何使用CHCSVParser类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆