Запись файла CSV в .net

43 год

У меня есть требование экспортировать набор данных в виде файла CSV.

Я потратил некоторое время на поиск набора правил и понял, что существует довольно много правил и исключений при написании файла CSV.

http://knab.ws/blog/index.php?/archives/3-CSV-file-parser-and-writer-in-C-Part-1.html http://bytes.com/topic/c- Sharp / answers / 236875-issues-streamwriter-output-csv http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/0073fcbb-adab-40f0-b768-4bba803d3ccd

Итак, теперь это непростой процесс разделения строк запятыми, я искал существующий писатель CSV либо сторонний, либо (надеюсь!) Включенный в структуру .net.

Изменить: новая ссылка: http://www.thinqlinq.com/Post.aspx/Title/LINQ-to-CSV-using-DynamicObject-and-TextFieldParser

TextFieldParser - это объект VB (на него можно ссылаться из C #), который автоматически анализирует файлы CSV. :)

Мне было интересно, знает ли кто-нибудь какие-нибудь удобные библиотеки .Net (2.0 -> 3.5 и 4.0), которые можно использовать для создания правильно отформатированного файла CSV.

Также, если есть какие-либо наборы правил для создания файлов CSV.

Есть много деталей о читателях CSV и анализе файлов CSV, но не так много о написании (хорошо, я знаю, что это как раз наоборот: P).

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

Любая помощь приветствуется :)

Я нашел другую статью с более подробными правилами CSV: http://www.creativyst.com/Doc/Articles/CSV/CSV01.htm

Изящная сторонняя библиотека - это Linq-to-CSV (не библиотека фреймворка): http://www.codeproject.com/KB/linq/LINQtoCSV.aspx

Спасибо за вашу помощь всем. Я решил, что лучшим решением будет создание простого статического класса, который будет выполнять замену специальных символов (о которых упоминал Крис).

Если бы мне понадобилось, чтобы Linq запрашивал мои CSV-файлы, я бы посмотрел на реализацию Linq-to-CSV в CodeProjects.

Спасибо еще раз :)

3
  • Я думаю, что, поскольку вы экспортируете, вы можете быть довольно расслаблены, когда пишете, если вы просто следуете общим правилам, большинство программ, таких как Excel, выясняют, как их читать.
    AndersK
    6 нояб.
  • Это правда. Я нахожусь в неудачном положении, когда пишу функцию «Экспорт», которая не определяет потенциальное использование. Я предполагаю, что в 99% случаев это будут отличные или, возможно (маловероятные) пакеты SSIS других приложений. Я могу только предполагать.
    Russell
    6 нояб.
  • Вы можете попробовать мой очень легкий редактор файлов с разделителями: gist.github.com/eranbetzalel/… 12 апр '13 в 13:18
21 год

Если в вашей ячейке есть запятые, заключите всю ячейку в двойные кавычки, например:

cell 1,cell 2,"This is one cell, even with a comma",cell4,etc

И если вам нужна буквальная двойная кавычка, сделайте две из них, например:

cell 1,cell 2,"This is my cell and it has ""quotes"" in it",cell 4,etc

Что касается дат, придерживайтесь формата ISO, и все будет в порядке (например, гггг-мм-дд чч: мм: сс)

7
  • 2
    Являются ли они единственными «правилами» сами по себе? Например, насчет новой строки. Знаете ли вы какие-либо ссылки на эти правила / требования? Я предполагаю (по результатам поиска), что для этих типов файлов не существует стандарта, а есть только требования к собственности (например, что будет работать с excel: P). Спасибо за ваш вклад.
    Russell
    6 нояб.
  • В принципе, я использую все, что работает с Excel. Что касается новых строк, все функции C # AppendLine и WriteLine, похоже, добавляют \ r \ n, что, похоже, согласуется с excel.
    Chris
    6 нояб.
  • И не забудьте заключить значения с новой строки в двойные кавычки. 21 янв.
  • 7
    Согласно en.wikipedia.org/wiki/Comma-separated_values этот ответ является простым для реальности требований форматирования CSV, если вам нужно быть строгим. 16 мар.
  • 2
    Кстати о датах: то, что вы указали, не является форматом ISO (используется ISO 8601 T, а не пространство для разделения даты и времени)
    Kos
    4 апр '12 в 13:46
50

CsvHelper (поддерживаемая мной библиотека) также доступен через NuGet.

CsvHelper может автоматически записывать объекты вашего класса в файл за вас.

var myObj = new MyCustomClass
{
    Prop1 = "one",
    Prop2 = 2
};
var streamWriter = // Create a writer to somewhere...
var csvWriter = new CsvWriter( streamWriter );

// You can write a single record.
csvWriter.WriteRecord( myObj );

// You can also write a collection of records.
var myRecords = new List<MyCustomClass>{ myObj };
csvWriter.WriteRecords( myRecords );
2
  • Кстати, в CsvHelper были добавлены некоторые функции сопоставления, которые позволяют отображать ваши классы без использования атрибутов. Вместо этого вы можете использовать свободный класс сопоставления, который позволяет вам сопоставлять классы, над которыми вы не можете контролировать. 13 дек.
  • Именно то, что я искал, и мне это очень понравилось! Спасибо.
    k427h1c
    30 окт.
18

Я просто хотел бы добавить, что есть RFC, который определяет формат CSV, который я считаю каноническим источником.

1
  • 1
    Спасибо, Ричард, это очень подробная информация :)
    Russell
    17 фев '10 в 7:41
6

Я широко использовал файловые помощники, и это довольно здорово для создания CSV.

3
  • Спасибо, FileHelpers выглядит очень удобной (+ с открытым исходным кодом) библиотекой. К сожалению, в этом случае я не могу добавлять атрибуты к своим объектам, которые я хотел бы преобразовать в CSV. Используя отражатель .net, я не видел способа сделать это, передав значения / списки. Вы знаете, возможно ли это?
    Russell
    6 нояб.
  • Вы можете просто создать несколько новых классов «только для генератора» и использовать AutoMapper для сопоставления ваших реальных классов с классами генератора, а затем записать эти классы с помощью FileHelpers. Я делал это раньше, и это довольно просто.
    lomaxx
    6 нояб.
  • Действительно ли filehelpers работают с CSV? Конечно, у них есть разделители, но это не то же самое, что CSV с правилами цитаты. 16 марта '11 в 2:08
4

Вот функция, которую вы можете использовать для создания строки CSV-файла из списка строк (также можно использовать IEnumerable (Of String) или массив строк):

Function CreateCSVRow(strArray As List(Of String)) As String
    Dim csvCols As New List(Of String)
    Dim csvValue As String
    Dim needQuotes As Boolean
    For i As Integer = 0 To strArray.Count() - 1
        csvValue = strArray(i)
        needQuotes = (csvValue.IndexOf(",", StringComparison.InvariantCulture) >= 0 _
                      OrElse csvValue.IndexOf("""", StringComparison.InvariantCulture) >= 0 _
                      OrElse csvValue.IndexOf(vbCrLf, StringComparison.InvariantCulture) >= 0)
        csvValue = csvValue.Replace("""", """""")
        csvCols.Add(If(needQuotes, """" & csvValue & """", csvValue))
    Next
    Return String.Join(",", csvCols.ToArray())
End Function

Как мне кажется, конвертировать с VB.NET на C # не составит труда)

1
  • Спасибо за информацию Евгений, уверен, будет полезно тем, кто сталкивается с этим вопросом. :)
    Russell
    19 ноя '13 в 20:28
3

Технические характеристики см. http://en.wikipedia.org/wiki/Comma-separated_values

3

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

Возможно, в вашем конкретном случае написать экспортер не так уж сложно, но хорошая вещь в этой библиотеке - то, что она двунаправленная. Если вам придется использовать CSV в будущем, это не так уж и много лишнего кода, и / или он дает вам согласованную библиотеку для использования в будущих проектах.

1
  • Спасибо, действительно очень удобно. У проектов разные требования и приоритеты, поэтому разные решения могут лучше подходить для разных проектов. Спасибо и не забудьте проголосовать, если вам это нравится. :)
    Russell
    6 нояб.
2

Вы можете использовать ODBC для чтения и записи файлов CSV (через OdbcConnection и подходящую строку подключения). Это должно быть достаточно хорошо для создания файлов CSV и позволит вам обрабатывать такие вещи, как цитирование; однако я столкнулся с некоторыми проблемами при использовании его для чтения файлов CSV, созданных другими программами.

2
  • 1
    Спасибо, есть ли ссылки для начала работы с этим методом?
    Russell
    6 нояб.
  • 1
    Если вы введете в Google запрос "odbc csv file", появится несколько хороших ссылок. Верхний - c-sharpcorner.com/UploadFile/mahesh/… - обратите внимание, что вам нужно будет прокрутить вниз, чтобы найти код C #! 6 нояб.
2

Еще одно правило, которое следует добавить к остальным: используйте запятые в качестве разделителей полей, а не в качестве разделителей полей. Причина этого в том, что конечная запятая в конце строки может быть неоднозначной: не имеет ли она никакого значения или означает ли она значение NULL после нее?

2
  • Очень хороший момент. Было бы неплохо иметь разделитель «конец строки» вместо использования новой строки. Например, разные ОС используют разные символы!
    Russell
    6 нояб.
  • 1
    Формат CSV определяет CRLF ("\ r \ n") как терминатор для каждой строки.
    Gusdor
    14 фев '12 в 15:31
0

Я нашел эту важную ссылку, которая довольно интересна. Еще не пробовал, дам знать, как идет!

http://www.codeproject.com/KB/linq/LINQtoCSV.aspx

Если присмотреться, то в этой реализации также используются только базовые правила:

специальные символы = \ n \ "и символ-разделитель.

если найдены специальные символы, заключите их в кавычки. Замените цитату двойной кавычкой.

По сути, правила, упомянутые Крисом. Я думаю, что самый простой способ сделать это - создать свой вспомогательный метод, основанный на простых правилах, и изменять его по мере необходимости.

0

Можете ли вы использовать массив строк, а затем объединить, используя:

string out = "";
string[] elements = { "1", "2" };
foreach(string s in elements) { out += s + "," };
out = out.substring(0, out.Length-1);
1
  • 1
    вы можете заменить приведенный выше код на String.Join (",", "1", "2", "etc ...");
    AndyD
    14 фев '13 в 15:08