Разбор строк с разделителями?

Я смотрю на синтаксический анализ строки с разделителями, что-то в порядке

a,b,c

Но это очень простой пример, и анализ данных с разделителями может оказаться сложным; например

1, "Ваш простой алгоритм, он не работает", Верно

взорвет вашу naiive string.Split реализацию на биты. Могу ли я свободно использовать / украсть / скопировать и вставить что-нибудь, что предлагает относительно надежное решение для анализа текста с разделителями? .NET, plox.

Обновление: я решил использовать TextFieldParser, который является частью кучи вкусностей VB.NET, спрятанных в Microsoft.VisualBasic.DLL.


person Community    schedule 13.08.2008    source источник


Ответы (9)


Я использую это для чтения из файла

string filename = @textBox1.Text;
string[] fields;
string[] delimiter = new string[] {"|"};
using (Microsoft.VisualBasic.FileIO.TextFieldParser parser =
       new Microsoft.VisualBasic.FileIO.TextFieldParser(filename)) {
    parser.Delimiters = delimiter;
    parser.HasFieldsEnclosedInQuotes = false;

    while (!parser.EndOfData) {
        fields = parser.ReadFields();
        //Do what you need
    }
}

Я уверен, что кто-то здесь может преобразовать это для синтаксического анализа строки, которая находится в памяти.

person Jedi Master Spooky    schedule 13.08.2008
comment
Возвращаясь к этому ответу, я все же считаю его лучшим. Я попробовал FileHelpers и пришел к выводу, что они меня пугают. Я не доверяю фреймворку, который полагается на порядок, в котором поля определены для типа. - person ; 22.12.2009

Здесь можно найти очень полную библиотеку: FileHelpers

person rohancragg    schedule 05.11.2008
comment
Я пробовал FileHelpers с тех пор, как задал этот вопрос, и мне очень не нравятся парсеры с разделителями. - person ; 22.12.2009

Я не знаю какой-либо структуры, но простой конечный автомат работает:

  • State 1: Read every char until you hit a " or a ,
    • In case of a ": Move to State 2
    • В случае: перейти в состояние 3
    • В случае конца файла: перейти в состояние 4
  • State 2: Read every char until you hit a "
    • In case of a ": Move to State 1
    • В случае конца файла: либо перейти в состояние 4, либо сообщить об ошибке из-за незавершенной строки
  • Состояние 3: добавить текущий буфер в выходной массив, переместить курсор вперед за и обратно в состояние 1.
  • Состояние 4: это конечное состояние, ничего не делает, кроме возврата выходного массива.
person Michael Stum    schedule 13.08.2008
comment
Строки CSV могут включать символы новой строки в текстовых кавычках, поэтому вы не можете сигнализировать об ошибке в состоянии 2, если конец строки. - person cjk; 26.02.2009
comment
На самом деле это правда, я всегда забываю о страшном символе \ n, который портит большинство парсеров CSV. Уточнено. - person Michael Stum; 26.02.2009

Такие как

var elements = new List<string>();
var current = new StringBuilder();
var p = 0;

while (p < internalLine.Length) {
    if (internalLine[p] == '"') {
        p++;

        while (internalLine[p] != '"') {
            current.Append(internalLine[p]);
            p++;
        }

        // Skip past last ',
        p += 2;
    }
    else {
        while ((p < internalLine.Length) && (internalLine[p] != ',')) {
            current.Append(internalLine[p]);
            p++;
        }

        // Skip past ,
        p++;
    }

    elements.Add(current.ToString());
    current.Length = 0;
}
person Stu    schedule 13.08.2008
comment
@ C1pher, пожалуйста, не вносите стилистических изменений, таких как брекетинг Java и C # / Pascal. - person StuartLC; 10.01.2014
comment
Согласованный. Я попытался отклонить это изменение, но оно уже было одобрено. - person Andy West; 10.01.2014
comment
К чему я хотел бы добавить, мы не занимаемся ни K&R, ни разработкой ядра Linux. FFS, ребята. - person Stu; 11.01.2014

Здесь есть несколько хороших ответов: Разделить строку, игнорируя цитируемые разделы

Возможно, вы захотите перефразировать свой вопрос на что-нибудь более точное (например, Какой фрагмент кода или библиотеку я могу использовать для анализа данных CSV в .NET?).

person Patrick McElhaney    schedule 13.08.2008

Чтобы сделать бессовестный плагин, я какое-то время работал над библиотекой под названием fotelo (Форматированный текст Loader), который я использую для быстрого анализа больших объемов текста на основе разделителя, позиции или регулярного выражения. Для быстрой строки это перебор, но если вы работаете с журналами или большими объемами, это может быть именно то, что вам нужно. Он работает на основе модели управляющего файла, подобной SQL * Loader (что-то вроде вдохновения).

person Dillie-O    schedule 13.08.2008

Лучше поздно, чем никогда (добавьте к полноте SO):

http://www.codeproject.com/KB/database/CsvReader.aspx

Это одно правило.

GJ

person gjvdkamp    schedule 30.06.2011

Я думаю, что в общей структуре необходимо указать между двумя вещами: 1. Какие символы-разделители. 2. При каком условии эти символы не учитываются (например, когда они заключены в кавычки).

Я думаю, что может быть лучше писать собственную логику каждый раз, когда вам нужно делать что-то подобное.

person Vaibhav    schedule 13.08.2008

Самый простой способ - просто разделить строку на массив символов и найти определители строк и разделить символ.

Модульное тестирование должно быть относительно простым.

Вы можете обернуть его в метод расширения, аналогичный базовому методу .Spilt.

person Keith    schedule 13.08.2008
comment
Строка по своей сути представляет собой массив символов, вам не нужно выполнять какое-либо преобразование - person cjk; 26.02.2009