Чтение CSV-файлов с использованием C #

Я пишу простое приложение импорта и вам нужно прочитать CSV-файл, показать результат в DataGrid и показать поврежденные строки файла CSV в другой сетке. Например, покажите строки, которые короче 5 значений в другой сетке. Я пытаюсь сделать это вот так:

 StreamReader sr = new StreamReader(FilePath); importingData = new Account(); string line; string[] row = new string [5]; while ((line = sr.ReadLine()) != null) { row = line.Split(','); importingData.Add(new Transaction { Date = DateTime.Parse(row[0]), Reference = row[1], Description = row[2], Amount = decimal.Parse(row[3]), Category = (Category)Enum.Parse(typeof(Category), row[4]) }); } 

но в этом случае очень сложно работать с массивами. Есть ли лучший способ разделить значения?

Не изобретайте велосипед. Воспользуйтесь тем, что уже есть в .NET BCL.

  • добавьте ссылку на Microsoft.VisualBasic (да, он говорит VisualBasic, но он также работает на C # – помните, что в конце это всего лишь IL)
  • используйте class Microsoft.VisualBasic.FileIO.TextFieldParser для parsingа CSV-файла

Вот пример кода:

 using (TextFieldParser parser = new TextFieldParser(@"c:\temp\test.csv")) { parser.TextFieldType = FieldType.Delimited; parser.SetDelimiters(","); while (!parser.EndOfData) { //Processing row string[] fields = parser.ReadFields(); foreach (string field in fields) { //TODO: Process field } } } 

Он отлично работает для меня в моих проектах на C #.

Вот еще несколько ссылок / информации:

  • MSDN: чтение текстовых файлов с разделителями-запятыми в Visual Basic
  • MSDN: class TextFieldParser

Мой опыт в том, что существует много разных форматов csv. Специально, как они обрабатывают экранирование кавычек и разделителей внутри поля.

Это варианты, с которыми я столкнулся:

  • котировки цитируются и удваиваются (превосходят), т.е. 15 “-> поле1,” 15 “” “, поле3
  • цитаты не изменяются, если поле не цитируется по какой-либо другой причине. т.е. 15 “-> поле1,15”, поля3
  • кавычки экранируются с помощью \. т.е. 15 “-> поле1,” 15 \ “”, поле3
  • кавычки вообще не меняются (это не всегда возможно правильно разобрать)
  • разделитель цитируется (excel). т.е. a, b -> поле1, «a, b», поле 3
  • разделитель с \. т.е. a, b -> field1, a \, b, field3

Я пробовал многие из существующих синтаксических анализаторов csv, но нет ни одного, который мог бы обрабатывать варианты, с которыми я столкнулся. Также трудно найти из документации, которая поддерживает варианты, которые поддерживают парсеры.

В моих проектах я теперь использую либо VB TextFieldParser, либо пользовательский разделитель.

Я рекомендую CsvHelper от Nuget .

(Добавление ссылки на Microsoft.VisualBasic просто не кажется правильным, это не только уродливо, это, вероятно, даже не межплатформенное.)

Иногда использование библиотек classно, когда вы не хотите изобретать колесо, но в этом случае можно выполнять ту же работу с меньшим количеством строк кода и читать легче по сравнению с использованием библиотек. Вот другой подход, который я считаю очень простым в использовании.

  1. В этом примере я использую StreamReader для чтения файла
  2. Regex для определения разделителя из каждой строки (линий).
  3. Массив для сбора столбцов от индекса 0 до n

 using (StreamReader reader = new StreamReader(fileName)) { string line; while ((line = reader.ReadLine()) != null) { //Define pattern Regex CSVParser = new Regex(",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))"); //Separating columns to array string[] X = CSVParser.Split(line); /* Do something with X */ } } 

CSV может быстро усложниться.

Используйте что-то надежное и проверенное:
FileHelpers: http://www.filehelpers.net

FileHelpers – бесплатная и простая в использовании библиотека .NET для импорта / экспорта данных с фиксированной длины или разделенных записей в файлах, строках или streamах.

Я использую это здесь:

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

В прошлый раз, когда я искал что-то подобное, я нашел его ответом на этот вопрос .

Еще один в этом списке, Cinchoo ETL – библиотека с открытым исходным кодом для чтения и записи CSV-файлов

Пример файла CSV ниже

 Id, Name 1, Tom 2, Mark 

Вы можете загрузить их с помощью библиотеки, как показано ниже.

 using (var reader = new ChoCSVReader("test.csv").WithFirstLineHeader()) { foreach (dynamic item in reader) { Console.WriteLine(item.Id); Console.WriteLine(item.Name); } } 

Если у вас есть class POCO, соответствующий CSV-файлу

 public class Employee { public int Id { get; set; } public string Name { get; set; } } 

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

 using (var reader = new ChoCSVReader("test.csv").WithFirstLineHeader()) { foreach (var item in reader) { Console.WriteLine(item.Id); Console.WriteLine(item.Name); } } 

Пожалуйста, ознакомьтесь с статьями в CodeProject о том, как их использовать.

Отказ от ответственности: я являюсь автором этой библиотеки

Прежде всего, нужно понять, что такое CSV и как его написать.

  1. Каждая следующая строка ( /r/n ) является следующей строкой «table».
  2. Ячейки «Таблица» разделяются символом разделителя. Чаще всего используются символы \t или ,
  3. Каждая ячейка может содержать этот символ разделителя (ячейка должна начинаться с символа кавычек и заканчивается этим символом в этом случае)
  4. Каждая ячейка может содержать /r/n sybols (ячейка должна начинаться с символа кавычек и заканчивается этим символом в этом случае)

Самый простой способ работы с CSV-файлами C # / Visual Basic – использовать стандартную библиотеку Microsoft.VisualBasic . Вам просто нужно добавить необходимую ссылку и следующую строку в ваш class:

 using Microsoft.VisualBasic.FileIO; 

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

Некоторое время назад я написал простой class для чтения / записи CSV на основе этой библиотеки. Используя этот простой class, вы сможете работать с CSV как с массивом размеров. Вы можете найти мой class по следующей ссылке: https://github.com/ukushu/DataExporter

Простой пример использования:

 Csv csv = new Csv("\t");//delimiter symbol csv.FileOpen("c:\\file1.csv"); var row1Cell6Value = csv.Rows[0][5]; csv.AddRow("asdf","asdffffff","5") csv.FileSave("c:\\file2.csv"); 

Чтобы завершить предыдущие ответы, может понадобиться коллекция объектов из его файла CSV, либо проанализированная TextFieldParser либо метод string.Split , а затем каждая строка преобразуется в объект через Reflection. Вы, очевидно, сначала должны определить class, который соответствует строкам CSV-файла.

Я использовал простой CSV-сериализатор от Майкла Кропата, найденный здесь: Общий class для CSV (все свойства) и использовал его методы для получения полей и свойств желаемого classа.

Я десериализую свой файл CSV следующим способом:

 public static IEnumerable ReadCsvFileTextFieldParser(string fileFullPath, string delimiter = ";") where T : new() { if (!File.Exists(fileFullPath)) { return null; } var list = new List(); var csvFields = GetAllFieldOfClass(); var fieldDict = new Dictionary(); using (TextFieldParser parser = new TextFieldParser(fileFullPath)) { parser.SetDelimiters(delimiter); bool headerParsed = false; while (!parser.EndOfData) { //Processing row string[] rowFields = parser.ReadFields(); if (!headerParsed) { for (int i = 0; i < rowFields.Length; i++) { // First row shall be the header! var csvField = csvFields.Where(f => f.Name == rowFields[i]).FirstOrDefault(); if (csvField != null) { fieldDict.Add(i, csvField); } } headerParsed = true; } else { T newObj = new T(); for (int i = 0; i < rowFields.Length; i++) { var csvFied = fieldDict[i]; var record = rowFields[i]; if (csvFied is FieldInfo) { ((FieldInfo)csvFied).SetValue(newObj, record); } else if (csvFied is PropertyInfo) { var pi = (PropertyInfo)csvFied; pi.SetValue(newObj, Convert.ChangeType(record, pi.PropertyType), null); } else { throw new Exception("Unhandled case."); } } if (newObj != null) { list.Add(newObj); } } } } return list; } public static IEnumerable GetAllFieldOfClass() { return from mi in typeof(T).GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static) where new[] { MemberTypes.Field, MemberTypes.Property }.Contains(mi.MemberType) let orderAttr = (ColumnOrderAttribute)Attribute.GetCustomAttribute(mi, typeof(ColumnOrderAttribute)) orderby orderAttr == null ? int.MaxValue : orderAttr.Order, mi.Name select mi; } 
 private static DataTable ConvertCSVtoDataTable(string strFilePath) { DataTable dt = new DataTable(); using (StreamReader sr = new StreamReader(strFilePath)) { string[] headers = sr.ReadLine().Split(','); foreach (string header in headers) { dt.Columns.Add(header); } while (!sr.EndOfStream) { string[] rows = sr.ReadLine().Split(','); DataRow dr = dt.NewRow(); for (int i = 0; i < headers.Length; i++) { dr[i] = rows[i]; } dt.Rows.Add(dr); } } return dt; } private static void WriteToDb(DataTable dt) { string connectionString = "Data Source=localhost;" + "Initial Catalog=Northwind;" + "Integrated Security=SSPI;"; using (SqlConnection con = new SqlConnection(connectionString)) { using (SqlCommand cmd = new SqlCommand("spInsertTest", con)) { cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.Add("@policyID", SqlDbType.Int).Value = 12; cmd.Parameters.Add("@statecode", SqlDbType.VarChar).Value = "blagh2"; cmd.Parameters.Add("@county", SqlDbType.VarChar).Value = "blagh3"; con.Open(); cmd.ExecuteNonQuery(); } } } - private static DataTable ConvertCSVtoDataTable(string strFilePath) { DataTable dt = new DataTable(); using (StreamReader sr = new StreamReader(strFilePath)) { string[] headers = sr.ReadLine().Split(','); foreach (string header in headers) { dt.Columns.Add(header); } while (!sr.EndOfStream) { string[] rows = sr.ReadLine().Split(','); DataRow dr = dt.NewRow(); for (int i = 0; i < headers.Length; i++) { dr[i] = rows[i]; } dt.Rows.Add(dr); } } return dt; } private static void WriteToDb(DataTable dt) { string connectionString = "Data Source=localhost;" + "Initial Catalog=Northwind;" + "Integrated Security=SSPI;"; using (SqlConnection con = new SqlConnection(connectionString)) { using (SqlCommand cmd = new SqlCommand("spInsertTest", con)) { cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.Add("@policyID", SqlDbType.Int).Value = 12; cmd.Parameters.Add("@statecode", SqlDbType.VarChar).Value = "blagh2"; cmd.Parameters.Add("@county", SqlDbType.VarChar).Value = "blagh3"; con.Open(); cmd.ExecuteNonQuery(); } } } 
  • Как я могу остановить Excel от употребления моих вкусных файлов CSV и извлечения бесполезных данных?
  • Импорт нескольких CSV-файлов в R
  • Самый простой способ открыть CSV с запятыми в Excel
  • Чтение даты и времени из файла CSV в MATLAB
  • Экспорт базы данных SQLite в файл csv в android
  • Разбор строки с разделителями-запятыми std :: string
  • Отправка массива значений в процедуру Oracle для использования в предложении WHERE IN
  • CSV на лист Excel снова
  • Сохранение листа Excel в CSV-файлах с именем файла + имя листа с использованием VB
  • Как я могу читать и редактировать данные файла CSV на C ++?
  • Чтение CSV со сканером ()
  • Interesting Posts

    Размер фонового изображения Android в пикселях

    Преобразование строки JSON в объект C #

    Динамическое программирование – Крупнейший квадратный блок

    Как изменить сокет TCP, чтобы он не блокировался?

    возобновление деятельности извещения

    выражать тело реакции каротажа

    WPF: удалите пунктирную рамку вокруг сфокусированного элемента в стилевом списке

    rxjs / Subject.d.ts error: Class ‘Subject ‘ неправильно расширяет базовый class ‘Observable ‘

    Создайте Multi-Bootable USB-диск для установки Win Xp, Windows 7 и Windows Server 2008

    Как обновить данные в одной таблице из соответствующих данных в другой таблице в SQL Server 2005

    Почему аргумент типа карты C ++ требует пустого конструктора при использовании ?

    Как сделать xampp безопасным

    Как пропустить проверку при нажатии на определенную кнопку?

    Как переместить кеш автономных файлов в Windows 7?

    Неужели дешевые маршрутизаторы легко перегружаются, когда к нему подключено множество устройств, и как я могу это исправить?

    Давайте будем гением компьютера.