我该在哪里找到一个用于Objective-C的将CSV转换为NSArray的解析器?

38

我正在寻找一个易于在iPhone上使用的Objective-C CSV解析器。您知道在哪里可以找到吗?

我还在寻找其他解析器,例如JSON,也许有转换库可以用。

8个回答

51

我终于抽出时间整理了一个解析器,将其发布在Github上:http://github.com/davedelong/CHCSVParser

它相当全面。它处理各种转义方案、字段中的换行符、注释等等。此外,它还使用智能文件加载,这意味着您可以在内存受限的情况下安全地解析大型文件。


我已经检查了您提供的Github链接,看起来没问题,但是当我试着在iPhone模拟器上测试时,它似乎不能正常工作。模拟器无法打开。同时基本的SDK设置为Mac OS X 10.5。所以这对于iPhone不起作用吗?应该怎么办?谢谢。 :) - Parth Bhatt
1
@PARTH 在 readme 的常用部分有一个文件列表。将它们复制到你的项目中,然后 #import "CHCSV.h" - Dave DeLong
感谢 Dave 回答我的愚蠢问题 :) 那么我想我们只需要使用 "arrayWithContentsofCSVFile:" 方法,对吗? - Parth Bhatt
@PARTH 那绝对是最简单的方法之一!如果你想的话,也可以选择整个带有委托的解析器路线。 - Dave DeLong

19

这是一个简单的NSString类别,用于解析包含在引号块内的逗号的CSV字符串。

#import "NSString+CSV.h"

@implementation NSString (CSV)

- (NSArray *)componentsSeparatedByComma
{
    BOOL insideQuote = NO;
    NSMutableArray *results = [[NSMutableArray alloc] init];
    NSMutableArray *tmp = [[NSMutableArray alloc] init];

    for (NSString *s in [self componentsSeparatedByString:@","]) {
        if ([s rangeOfString:@"\""].location == NSNotFound) {
            if (insideQuote) {
                [tmp addObject:s];
            } else {
                [results addObject:s];
            }
        } else {
            if (insideQuote) {
                insideQuote = NO;
                [tmp addObject:s];
                [results addObject:[tmp componentsJoinedByString:@","]];
                tmp = nil;
                tmp = [[NSMutableArray alloc] init];
            } else {
                insideQuote = YES;
                [tmp addObject:s];
            }
        }
    }

    return results;
}

@end

这个假设您已经将CSV文件读入数组中:

myArray = [myData componentsSeparatedByString:@"\n"];

该代码未考虑转义引号,但很容易进行扩展。


8
快速实现方法: NSString *dataStr = [NSString stringWithContentsOfFile:@"example.csv" encoding:NSUTF8StringEncoding error:nil]; NSArray *array = [dataStr componentsSeparatedByString: @","];

1
这个方法无法处理包含逗号的块,这就是为什么你经常需要一个完整的库 :) - willcodejavaforfood
今天我不需要,但了解那个方法/消息也是好的。 - Toby Allen

5

好的,上述简单解决方案并没有考虑到多条记录。使用以下代码读取默认的Excel CSV,并使用ASCII 13作为行结束标记:

NSString *content =  [NSString stringWithContentsOfFile:filepath encoding:NSUTF8StringEncoding error:nil];
NSArray *contentArray = [content componentsSeparatedByString:@"\r"]; // CSV ends with ACSI 13 CR (if stored on a Mac Excel 2008)

for (NSString *item in contentArray) {
    NSArray *itemArray = [item componentsSeparatedByString:@";"];
    // log first item
    NSLog(@"%@",[itemArray objectAtIndex:0]);
}

你必须考虑到,虽然这对于简单文件可能有效,但在许多情况下不起作用。有些情况下您可以逃脱逗号,或者将值放在引号内。componentsSeparatedByString将无法捕捉到这些情况。还有一些情况是单元格的值可能包含换行符,因此在这些情况下,您的内容数组也将不准确。这就是为什么其他人建议使用库(比如CHCSV解析器)的原因。这些库被设计来处理所有这些情况。 - Rob

3

我为我正在处理的项目编写了一个非常简单(尽管不是完全功能齐全)的CSV解析器:CSVFile.hCSVFile.m。随意使用它--代码在GPLv3下可用(不幸的是,这是我正在工作的项目的要求),但我很乐意将其许可给您以MIT许可证或其他许可证。


1

这似乎是我目前找到的最全面的。

http://www.macresearch.org/cocoa-scientists-part-xxvi-parsing-csv-data

作为一个旁注,你会认为大多数主要的编程语言(如Delphi、C#、Objective-c、php等)都应该有一个可用的库,其中包含了这种基本数据交换格式的完整实现。
我知道json很酷,XML很可靠,但是它们都不能作为大多数应用程序保存表格数据的选项。CSV仍然是最好的选择。

0

几周前我发现了ParseKit 但在我看来,对于大多数情况来说,-[NSString componentsSeparatedByString:]方法和NSScanner已经足够并且非常容易使用。


谢谢,不过看起来有点复杂,不太符合我的需求。 - Toby Allen

-2
如xmr所述:在Objective C中,可以将NSString csv转换为“由字符串分隔的组件”数组。
    NSArray* items;
    items=[bufferString componentsSeparatedByString:@","];       

如果你对CSV导出感兴趣,就像我一样来到这个帖子,这里是我导出CSV文件的摘录。
    NSString* fileName    = @"Level";
    fileName = [fileName stringByAppendingString:levelNumberBeingEdited];
    fileName = [fileName stringByAppendingString:@".txt"];
    NSString* bufferString=@"";  

通过循环遍历每个数据项(未显示)并在它们之间插入逗号,填充缓冲字符串。最后导出。

    NSString* homeDir = NSHomeDirectory();
    NSString* fullPath = [homeDir stringByAppendingPathComponent:fileName];
    NSError* error = nil;
    [bufferString writeToFile:fullPath atomically:NO encoding:NSASCIIStringEncoding error:&error];

7
无论这是什么,它都不是有关如何解析CSV文件的答案。已标记。 - Dave DeLong
1
我已经编辑了我的答案。我被引导到这个帖子,xmr解决了我的问题。我认为展示实际csv文本文件如何适用于他的解决方案会很有用。 - Barnaby Byrne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接