【问题标题】:Parsing CSV: how can NSScanner recognize empty field (i.e. ,,)?解析 CSV:NSScanner 如何识别空字段(即,,)?
【发布时间】:2011-08-11 00:23:26
【问题描述】:

我对 Xcode 非常陌生,并尝试(以百万计)解析 CSV 文件。我已经阅读了很多贡献并且我正在管理它,但是当我的 NSScanner 截获一个空字段时我遇到了问题:“Field_A,Field_B,,Field_D”。我猜这是因为它默认忽略空白,或者在这种情况下根本没有空间。

字符串是:

"个人","2011-01-01","个人","香烟",,4.60,"现金","",

我尝试使用 scanLocation 对其进行调试:

2011-04-22 15:57:32.414 Spending[42015:a0f] Before while...scan location is:0
2011-04-22 15:57:32.414 Spending[42015:a0f] Account: "Personal" - scan location is:10
2011-04-22 15:57:32.415 Spending[42015:a0f] Date: "2011-01-01" - scan location is:23
2011-04-22 15:57:32.415 Spending[42015:a0f] Category: "Personal" - scan location is:34
2011-04-22 15:57:32.416 Spending[42015:a0f] Subcategory: "Cigarettes" - scan location is:47
2011-04-22 15:57:32.416 Spending[42015:a0f] Income: 4.600000 - scan location is:53
2011-04-22 15:57:32.416 Spending[42015:a0f] Expense: 0.000000 - scan location is:53
2011-04-22 15:57:32.417 Spending[42015:a0f] Payment: "Cash" - scan location is:60
2011-04-22 15:57:32.417 Spending[42015:a0f] Note: "" - scan location is:63

正如您所见,即使费用字段也没有任何价值(应该是 4.60)。

以下是相关代码:

NSScanner *scanner = [NSScanner scannerWithString:fileString];
    [scanner setCharactersToBeSkipped: [NSCharacterSet characterSetWithCharactersInString:@"\n, "]];

    NSString *account, *date, *category, *subcategory, *payment, *note;
    float income, expense;

    // Set up data delimiter using comma
    NSCharacterSet *commaSet;
    commaSet = [NSCharacterSet characterSetWithCharactersInString:@","];

    NSLog (@"Before while...scan location is:%d\n", scanner.scanLocation);

    [scanner scanUpToCharactersFromSet:commaSet intoString:&account];
    NSLog(@"Account: %@ - scan location is:%d\n",account, scanner.scanLocation);

    [scanner scanUpToCharactersFromSet:commaSet intoString:&date];
    NSLog(@"Date: %@ - scan location is:%d\n",date, scanner.scanLocation);

    [scanner scanUpToCharactersFromSet:commaSet intoString:&category]; 
    NSLog(@"Category: %@ - scan location is:%d\n",category, scanner.scanLocation);

    [scanner scanUpToCharactersFromSet:commaSet intoString:&subcategory]; 
    NSLog(@"Subcategory: %@ - scan location is:%d\n",subcategory, scanner.scanLocation);

    [scanner scanFloat:&income];
    NSLog(@"Income: %f - scan location is:%d\n",income, scanner.scanLocation);

    [scanner scanFloat:&expense]; 
    NSLog(@"Expense: %f - scan location is:%d\n",expense, scanner.scanLocation);

    [scanner scanUpToCharactersFromSet:commaSet intoString:&payment]; 
    NSLog(@"Payment: %@ - scan location is:%d\n",payment, scanner.scanLocation);

    [scanner scanUpToCharactersFromSet:commaSet intoString:&note];
    NSLog(@"Note: %@\n - scan location is:%d",note, scanner.scanLocation);

我尝试仔细查看 NSScanner 类参考,但无法理解?你有什么?

谢谢,法布里齐奥。

【问题讨论】:

  • 至少修复 NSLogs 以显示 incomeexpense 而不是 &income&expense
  • 是的,你是对的,现在换帖子!

标签: objective-c xcode csv nsscanner


【解决方案1】:

在 Objective-C 中解析 CSV?这听起来很熟悉:

https://github.com/davedelong/CHCSVParser

免责声明:我写的。 :)


对于您正在做的事情,您可以直接获取文件并通过+[NSArray arrayWithContentsOfCSVFile:encoding:error:] 方法之类的方法运行,或者您可以将其读入字符串并执行以下操作:

NSString *csv = @"\"Personal\",\"2011-01-01\",\"Personal\",\"Cigarettes\",,4.60,\"Cash\",\"\",";
NSLog(@"%@", [csv CSVComponents]);

哪些日志:

2011-04-22 09:51:16.651 CHCSVParser[2658:903] (
        (
        Personal,
        "2011-01-01",
        Personal,
        Cigarettes,
        "",
        "4.60",
        Cash,
        ""
    )
)

(请注意,这是NSArrayNSArraysNSStrings

如果您担心内存堆积,那么您也可以直接使用CHCSVParser 并通过委托接收信息。它的运作方式与NSXMLParser 的运作方式几乎相同。

【讨论】:

  • 顺便说一句:这也是我用过的一个很好的解决方案。
  • 嗨,戴夫,感谢您对 arrayWithContentsOfCSVFile 的建议,我会看看它。关于您发布的代码,只有一个问题:我无法编辑添加反斜杠的字符串。无论如何,我会看看你的代码,也许会找到我需要的提示。
  • 谢谢你,Dave,我已经尝试过你的代码并且运行顺利。我不得不承认我更喜欢只使用objective-c解决方案而不添加其他代码来解决我的问题,但是你的课程在写作方面也会很有帮助,因此谢谢!
  • @Fabrizio 反斜杠只是为了让字符串正确编译。它们实际上并不存在于最终字符串中(\" 是您如何让 " 出现在字符串中)
  • 是的,我也有机会注意到 Dave,并且使用 arrayWithContentsOfCSVString 完全符合我的需要,同时也识别了空字段......现在我还有很多其他问题要解决应用程序部署(多么新手!)...我肯定很快就会需要其他帮助 :) 非常感谢。
【解决方案2】:

扫描仪看不到您的空白字段的原因是您告诉它跳过逗号。你用一组 3 个字符调用了 setCharactersToBeSkipped:

  1. '\n' 换行符
  2. ',' 逗号
  3. ''空格

当您让扫描仪“scanFloat”时,它会遍历任何可跳过的字符,直到达到十进制数。这就是跳过空字段的方式。

如果要捕获空字段,请从字符集中删除逗号以跳过。然后,任何时候扫描函数找到一个空字段,它都会返回 NO。发生这种情况时,您可能必须手动增加扫描位置。

【讨论】:

    【解决方案3】:

    看看this article on CSV 扫描仪。

    这是另一个article

    Dave DeLong 的解决方案也很有效。

    底线:CSV 看起来微不足道,但如果您想优雅地处理任何扔给您的 CSV,它确实不是。

    【讨论】:

    • 我已经做过,但会再做一次,也许我错过了什么......谢谢。
    • 我将检查 Dave 代码,其他两篇文章是我一直在使用的,但它们似乎并没有解决我的空字段问题。无论如何,谢谢你的回答:)
    猜你喜欢
    • 2017-06-30
    • 1970-01-01
    • 2013-11-28
    • 2017-12-04
    • 1970-01-01
    • 1970-01-01
    • 2013-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多