Парсинг CSV: как NSScanner может распознать пустое поле (т.е. ,,)? - PullRequest
3 голосов
/ 22 апреля 2011

Я очень новичок в Xcode и пытаюсь - как миллионы - проанализировать файл CSV.Я прочитал много статей и управляю ими, но у меня проблема, когда мой NSScanner перехватывает пустое поле: «Field_A, Field_B ,, Field_D».Я предполагаю, что это потому, что он игнорирует пустое пространство по умолчанию, или в этом случае вообще нет места.

Строка:

"Personal", "2011-01-01", "Personal"," Сигареты ",, 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, но не смог понять?У тебя есть?

Спасибо, Фабрицио.

Ответы [ 3 ]

2 голосов
/ 22 апреля 2011

Разбор CSV в Objective-C?Звучит знакомо:

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,
        ""
    )
)

(Обратите внимание, что это NSArray из NSArrays из NSStrings)

Если вы обеспокоеныЧто касается накопления памяти, то вы также можете использовать CHCSVParser напрямую и получать информацию через делегата.Он работает почти так же, как NSXMLParser.

0 голосов
/ 08 июля 2012

Причина, по которой сканер не видит ваше пустое поле, заключается в том, что вы сказали, чтобы оно пропускало запятые.Вы вызвали setCharactersToBeSkipped с набором из 3 символов:

  1. '\ n' Символ новой строки
  2. ',' Запятая
  3. '' Пробел

Когда вы затем просите сканер «scanFloat», он перебирает любой пропускаемый символ, пока не достигнет десятичного числа.Вот как пропускается пустое поле.

Если вы хотите перехватить пустые поля, удалите запятую из набора символов, чтобы пропустить.Затем, каждый раз, когда функция сканирования находит пустое поле, она возвращает NO.В этом случае вам может потребоваться увеличить позицию сканирования вручную.

0 голосов
/ 22 апреля 2011

Ознакомьтесь с этой статьей о сканерах CSV.

Вот еще одна статья

Решение Дейва Делонга также прекрасно работает.

Итог: CSV кажется тривиальным, но на самом деле это не так, если вы хотите справиться с любым CSV, брошенным на вас изящно.

...