代码之家  ›  专栏  ›  技术社区  ›  Neal L

如何使用CHCSVParser类

  •  13
  • Neal L  · 技术社区  · 14 年前

    我在和戴夫·德龙的绝活玩儿 CHCSVParser 对于Objective-C,它有一个非常长的.CSV文件,我在使用它时遇到了一些问题。我会用 arrayWithContentsOfCSVFile 方法,但我在iPhone上运行代码,将整个文件解析到内存将占用比可用内存更多的内存。

    在我下面的代码中,解析器打开文档并完美地调用委托方法,但是在委托中,我在每一行之后停在哪里访问数据(创建一个核心数据对象并将其保存到数据存储)?我想那应该在 - (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]);
    }
    

    谢谢!

    2 回复  |  直到 10 年前
        1
  •  17
  •   Dave DeLong    14 年前

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

    CHCSVParser 在行为上类似于 NSXMLParser CHCSVParser公司 NSXML解析器 )你真蠢。他们只知道他们试图解析的内容的格式,但实际上并没有做更多的事情。

    因此,简单地说,答案是“你必须自己拯救它”。如果你看一下 NSArray a simple NSObject subclass as the parser delegate ,子类将字段聚合到一个数组中,然后将该数组添加到整个数组中。你需要做类似的事情。

    @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
    

    然而,我可以确信修改解析器的行为来聚合行本身,但是如果我沿着这条路线走,为什么不让解析器聚合整个文件呢?(回答:不应该)

        2
  •  1
  •   njr0    11 年前

    基于@DaveDeLong出色的答案和代码,我今天尝试使用这个软件,但我认为自从他(2010)的答案之后,这个软件已经被修改了。在写作的时候,我发现我必须用这个:

    @interface CSVParserDelegate : NSObject <CHCSVParserDelegate> {
      NSMutableArray * currentRow;
    }
    @end
    
    @implementation CSVParserDelegate
    
    - (void) parser:(CHCSVParser *)parser didBeginLine:(NSUInteger)lineNumber {
      currentRow = [[NSMutableArray alloc] init];
    }
    - (void) parser:(CHCSVParser *)parser didReadField:(NSString *)field atIndex:(NSInteger)fieldIndex {
      [currentRow addObject:field];
    }
    - (void) parser:(CHCSVParser *)parser didEndLine:(NSUInteger)lineNumber {
      NSLog(@"finished line! %@", currentRow);
      [self doSomethingWithLine:currentRow];
      [currentRow release], currentRow = nil;
    }
    @end
    

    即。, parser:didStartLine:lineNumber: 已经变成 parser:didBeginLine:lineNumber: parser:didReadField: 已经变成 parser:didReadField:atIndex: .

        3
  •  0
  •   Leonid Silver    4 年前

    要将CHCSVParser与Swift一起使用,可以使用 a swift wrapper