将远程CSV加载到CHCSVParser

3

我正在使用Dave DeLong的CHCSVParser解析CSV文件。我可以解析本地的CSV文件,但是我无法加载远程的CSV文件。今天我一直盯着我的MacBook看,答案就在我面前。这是我的代码:

NSString *urlStr = [[NSString alloc] initWithFormat:@"http://www.somewhere.com/LunchSpecials.csv"];
NSURL *lunchFileURL = [NSURL URLWithString:urlStr];
NSStringEncoding encoding = 0;
CHCSVParser *p = [[CHCSVParser alloc] initWithContentsOfCSVFile:[lunchFileURL path] usedEncoding:&encoding error:nil];
[p setParserDelegate:self];
[p parse];
[p release];

感谢任何能够提供帮助的人。

1
我可以非常确定,这个人会回答你的问题。请耐心等待。 - Jacob Relkin
@Jacob 听起来像是一个相当安全的赌注。 ;) - Dave DeLong
2个回答

6
-[NSURL path]并不会做你期望的事情。如果我有一个URL为https://dev59.com/E1PTa4cB1Zd3GeqPhTt3,那么它的-path/questions/4636428。当你将该路径传递给CHCSVParser时,它将尝试在本地系统上打开该路径。由于该文件不存在,因此您将无法打开它。
你需要做的(正如Walter所指出的)是在本地下载CSV文件,然后打开它。您可以通过几种不同的方式下载文件(+[NSString stringWithContentsOfURL:...]NSURLConnection等)。一旦您将文件保存到本地磁盘或内存中的CSV字符串,就可以将其传递给解析器。
如果这是一个非常大的文件,则需要使用CSV文件的本地副本的路径来alloc/init一个CHCSVParser。然后,解析器将逐位读取它,并通过委托回调告诉您它找到了什么。
如果CSV文件不是很大,则可以执行以下操作:
NSString * csv = ...; //the NSString containing the contents of the CSV file
NSArray * rows = [csv CSVComponents];

这将返回一个由NSStringsNSArrays组成的NSArray

类似于上一种方法,可以使用NSArray类别方法:

NSString * csv = ...;
NSError * error = nil;
NSArray * rows = [NSArray arrayWithContentsOfCSVString:csv encoding:[csv fastestEncoding] error:&error];

这将返回相同的结构(一个NSArray,其中包含NSStringsNSArrays),但如果在CSV文件中遇到语法错误(即,格式不正确的CSV),它还会提供一个NSError对象。


感谢 Dave 的帮助!这解决了我很多问题。顺便说一下,你的解析器真棒!!它对我的应用程序非常有用。 - Matt
@Dave CHCSVParser 包含一个 NSString 的分类?太酷了! - Jacob Relkin
@Jacob Relkin没错,还有NSArray - Dave DeLong
@Dave 是的,没错。我浏览了整个 Github 仓库 - 它非常不错! - Jacob Relkin
嘿,戴夫!我已经将远程csv加载到我的数组中,但现在我有一个不同的问题。由于某种原因,在Windows计算机上使用Excel添加元素到电子表格时,解析器会在数组末尾添加一个空对象。在我使用Mac的Excel时不会发生这种情况。我需要更改Windows计算机中的设置吗?我确实将Windows计算机更改为以UTF8编码csv。不确定还要做什么。我正在尝试编写一段代码来检查数组中最后一个对象是否为空。 - Matt
显示剩余5条评论

1

我认为你需要一个NSString对象而不是NSURL对象传递给解析器,所以你将NSString转换成NSURL的这个额外步骤可能是问题所在。从CHCSVParser文档来看,初始化方法需要一个NSString参数。

因此,你可以尝试这样做:

NSError *err = [[[NSError alloc] init] autorelease];
NSString *lunchFileURL = [[NSString stringWithFormat:@"http://www.somewhere.com/LunchSpecials.csv"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *lunchFile = [NSString stringWithContentsOfURL:[NSURL URLWithString:lunchFileURL] encoding:NSUTF8StringEncoding error:&err];
CHCSVParser *p = [[CHCSVParser alloc] initWithContentsOfCSVString:lunchFile usedEncoding:&encoding error:nil];

原则上正确,实现上有误。CHCSVParser确实没有使用NSURL,这一点是正确的。但是NSString并没有-path方法,而且“lunchFile”变量包含的是CSV文件的内容,而不是磁盘上的物理文件。 - Dave DeLong
感谢Dave的建议。我已经根据你的更正建议更新了示例,现在它是正确的。我直接保留了字符串,而不是将“lunchFile”变量保存到磁盘上再读取回来。 - Walter

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