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

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

а, б, в

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

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

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

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

Ответов (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
    }
}

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

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

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

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

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

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

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

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

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

  • Состояние 1. Прочтите все символы, пока не нажмете "или",
    • В случае ": перейти в состояние 2"
    • В случае: перейти в состояние 3
    • В случае конца файла: перейти в состояние 4
  • Состояние 2: прочитайте все символы, пока не нажмете "
    • В случае ": перейти в состояние 1"
    • В случае конца файла: либо перейти в состояние 4, либо сообщить об ошибке из-за незавершенной строки
  • Состояние 3: добавить текущий буфер в выходной массив, переместить курсор вперед за и обратно в состояние 1.
  • Состояние 4: это конечное состояние, ничего не делает, кроме возврата выходного массива.

Такие как

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;
}

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

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

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

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

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

ГДж