Написание и полировка парсера CSV - PullRequest
4 голосов
/ 13 февраля 2012

В рамках недавнего проекта мне пришлось читать и писать из CSV-файла и вставлять в сетку в C #. В конце концов решил использовать готовый парсер, чтобы сделать работу за меня.

Поскольку мне нравится заниматься такими вещами, я удивлялся, как писать свои собственные.

Пока все, что мне удалось сделать, это:

//Read the header
            StreamReader reader = new StreamReader(dialog.FileName);
            string row = reader.ReadLine();
            string[] cells = row.Split(',');

            //Create the columns of the dataGridView
            for (int i = 0; i < cells.Count() - 1; i++)
            {
                DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn();
                column.Name = cells[i];
                column.HeaderText = cells[i];
                dataGridView1.Columns.Add(column);
            }

            //Display the contents of the file
            while (reader.Peek() != -1)
            {
                row = reader.ReadLine();
                cells = row.Split(',');
                dataGridView1.Rows.Add(cells);
            }

Мой вопрос: продолжает ли это мудрая идея, и если она есть (или нет), как бы я ее правильно проверил?

Ответы [ 5 ]

7 голосов
/ 13 февраля 2012

Как упражнение по программированию (для обучения и получения опыта) это, вероятно, очень разумная вещь. Для производственного кода может быть лучше использовать существующую библиотеку главным образом потому, что работа уже выполнена. Есть довольно много вещей, с которыми нужно разобраться с парсером CSV. Например (случайно с макушки головы):

  • Цитируемые значения (строки)
  • Встроенные кавычки в цитируемых строках
  • Пустые значения (NULL ... или, может быть, даже NULL против пустых).
  • Строки без правильного количества записей
  • Заголовки против заголовков.
  • Распознавание разных типов данных (например, разных форматов даты).

Если у вас очень специфический формат ввода в очень контролируемой среде, вам, возможно, не придется иметь дело со всеми из них.

2 голосов
/ 13 февраля 2012

Получить (или создать) некоторые данные CSV и записать Модульные тесты с использованием NUnit или Инструменты тестирования Visual Studio .

Обязательно протестируйте крайние случаи, такие как

"csv","Data","with","a","trailing","comma",

и

"csv","Data","with,","commas","and","""quotes""","in","it"
1 голос
/ 14 февраля 2012

... продолжает эту мудрую идею ...?

Поскольку вы делаете это как учебное упражнение, вы можете углубиться в lexing и парсинг теория.Ваш текущий подход довольно быстро покажет свои недостатки, как описано в Хватит качать собственный CSV-парсер! .Дело не в том, что анализ CSV-данных затруднен.(Это не так.) Просто большинство проектов парсеров CSV рассматривают проблему как проблему разделения текста, а не как проблему синтаксического анализа.Если вы потратите время на определение "языка" CSV, то синтаксический анализатор почти напишет сам.

RFC 4180 определяет грамматику для данных CSV в ABNF форме:

file = [header CRLF] record *(CRLF record) [CRLF]
header = name *(COMMA name)
record = field *(COMMA field)
name = field
field = (escaped / non-escaped)
escaped = DQUOTE *(TEXTDATA / COMMA / CR / LF / 2DQUOTE) DQUOTE
non-escaped = *TEXTDATA
COMMA = %x2C
CR = %x0D ;as per section 6.1 of RFC 2234
DQUOTE =  %x22 ;as per section 6.1 of RFC 2234
LF = %x0A ;as per section 6.1 of RFC 2234
CRLF = CR LF ;as per section 6.1 of RFC 2234
TEXTDATA =  %x20-21 / %x23-2B / %x2D-7E

Эта грамматика показывает, как создаются отдельные символы для создания более сложных языковых элементов.(Как написано, определения идут в обратном направлении от сложного к простому.)

Если вы начинаете с грамматики, вы можете написать функции синтаксического анализа, которые отражают нетерминальные элементы грамматики (строчные элементы).Джулиан М. Бакнолл описывает процесс в Написание парсера для данных CSV .Взгляните на Test-Driven Development с ANTLR для примера того же процесса с использованием генератора синтаксического анализатора.

Имейте в виду, что нет единого принятого определения CSV.Данные CSV в дикой природе не гарантируют реализацию всех предложений RFC 4180.

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

Это происходит от http://www.gigawebsolution.com/Posts/Details/61/Building-a-Simple-CSV-Parser-in-C#

public interface ICsvReaderWriter
{
    List<string[]> Read(string filePath, char delimiter);
    void Write(string filePath, List<string[]> lines, char delimiter);
}

public class CsvReaderWriter : ICsvReaderWriter
{
    public List<string[]> Read(string filePath, char delimiter)
    {
        var fileContent = new List<string[]>();
        using (var reader = new StreamReader(filePath, Encoding.Unicode))
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                if (!string.IsNullOrEmpty(line))
                {
                    fileContent.Add(line.Split(delimiter));
                }
            }
        }
        return fileContent;
    }

    public void Write(string filePath, List<string[]> lines, char delimiter)
    {
        using (var writer = new StreamWriter(filePath, true, Encoding.Unicode))
        {
            foreach (var line in lines)
            {
                var data = line.Aggregate(string.Empty,
                                         (current, column) => current +
                                          string.Format("{0}{1}", column,delimiter))
                    .TrimEnd(delimiter);
                writer.WriteLine(data);
            }
        }
    }
}
0 голосов
/ 14 февраля 2012

Анализ файла CSV не сложен, но он включает в себя больше, чем просто вызов String.Split().

Вы разбиваете строки в каждой запятой.Но поля могут содержать запятые.В этих случаях CSV переносит поле в двойные кавычки.Поэтому вы также должны искать двойные кавычки и игнорировать запятые в этих кавычках.Кроме того, поля могут даже содержать двойные кавычки.Двойные кавычки должны появляться в двойных кавычках и быть «удвоены», чтобы указать, что цитата является буквальным символом.

Если вы хотите посмотреть, как я это сделал, вы можете проверить эту статью .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...