【问题标题】:scanUpToCharactersFromSet stops after one loopscanUpToCharactersFromSet 在一个循环后停止
【发布时间】:2010-01-22 06:58:17
【问题描述】:

我正在尝试将 CSV 文件的内容放入数组中。当我在每行有一条记录之前完成此操作,并使用带有scanUpToCharactersFromSet:intoString: 的换行符,将newlineCharacterSet 作为字符集传递:

while ([lineScanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet] 
                                   intoString:&line])

现在,我正在处理一个文件,其中许多条目本身都包含换行符。我尝试在每条记录的末尾添加一个唯一字符(* 字符),但我的循环只运行一次。有什么东西让我不知道while循环中断吗?这是我现在使用的代码:

NSError *error;
NSString *data = [[NSString alloc] initWithContentsOfFile:[[self delegate] filePath] encoding:NSUTF8StringEncoding error:&error];
NSScanner *lineScanner = [NSScanner scannerWithString:data];
NSString *line = nil;

// Start parsing the CSV file
while ([lineScanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"*"]
                    intoString:&line]) {
    NSArray *elements = [line componentsSeparatedByString:@","];
    NSLog("Name: %@", [elements objectAtIndex:1]);
}

**编辑:**感谢彼得在下面的回答,我发现我的扫描仪卡在 * 字符后面。我在循环中添加了这一行:

[lineScanner scanCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"*"] intoString:NULL];

现在它可以正常工作了。

【问题讨论】:

  • 您不需要 * 分隔符。您可以很好地扫描纯换行符(现在您的循环已修复)。

标签: objective-c csv cocoa lexical-analysis


【解决方案1】:

让我们一次过一遍:

  1. 第一:

    while ([lineScanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:[NSCharacterSet newlineCharacterSet]] intoString:&line]) {
    

    扫描程序将换行符之前的所有内容放入line。它前进到换行符。

  2. 第二:

    while ([lineScanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:[NSCharacterSet newlineCharacterSet]] intoString:&line]) {
    

    扫描仪已经在换行,所以它不扫描任何字符。 As documented,因为它没有扫描任何字符,所以它返回NO。您的循环终止。

解决方案是在循环结束时scan the line break,让扫描仪通过它。假设您不关心换行符是什么,您可以将NULL 传递给输出参数。

这是正确的行为:如果您确实/确实关心您扫描到的字符是什么,这可以让您获得它们。如果 NSScanner 自动扫描过去的字符,那将更加困难。

【讨论】:

  • 感谢彼得的回答。使用[NSCharacterSet newlineCharacterSet] 的循环在使用每行一条记录的 CSV 文件时运行良好。使用多行记录 CSV,我在每条记录的末尾放了一个 * 并尝试了 [NSCharacterSet characterSetWithCharactersInString:@"*"] 但它失败了。大概卡在 * 字符上。我考虑了您的答案并添加了上面的代码。现在它起作用了。谢谢。
【解决方案2】:

我认为 while 条件是错误的。根据String Programming Guide,应该是这样的:

while ([theScanner isAtEnd] == NO) {
    [lineScanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"*"] intoString:&line]
    // ...
}

【讨论】:

  • 只要还有东西需要扫描,isAtEnd 就不会返回YES。因此,这是一个无限循环,因为它永远不会扫描超过第一行的末尾。看我的回答。
猜你喜欢
  • 2021-09-15
  • 1970-01-01
  • 1970-01-01
  • 2022-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多