2015-10-23 2 views
8

Итак, я читал, что не должен писать свой собственный CSV-ридер/писатель, поэтому я пытался использовать библиотеку CsvHelper, установленную через nuget. CSV-файл представляет собой изображение с серой шкалой, при этом количество строк является высотой изображения и числом столбцов шириной. Я хотел бы прочитать значения row-wise в одном List<string> или List<byte>.Прочитайте все значения из CSV в список с помощью CsvHelper

код у меня до сих пор:

using CsvHelper; 

public static List<string> ReadInCSV(string absolutePath) 
{ 
    IEnumerable<string> allValues; 

    using (TextReader fileReader = File.OpenText(absolutePath)) 
    { 
     var csv = new CsvReader(fileReader); 
     csv.Configuration.HasHeaderRecord = false; 
     allValues = csv.GetRecords<string> 
    } 

    return allValues.ToList<string>(); 
} 

Но allValues.ToList<string>() бросает:

CsvConfigurationException был необработанным кодом пользователя

исключения типа «CsvHelper.Configuration .CsvConfigurationException 'произошел в CsvHelper.dll, но не был обработан в коде пользователя

Дополнительная информация: Типы, наследующие IEnumerable, не могут быть автоматически сопоставлены. Вы случайно вызвали GetRecord или WriteRecord, которые действуют на одну запись, вместо того, чтобы вызывать GetRecords или WriteRecords, которые действуют в списке записей?

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

+0

Можете ли вы дать нам дополнительную информацию об исключении CsvConfiguration? Есть ли сообщение? – masinger

+1

Вызов .ToLIst(), как это почти всегда ошибка. Оставайтесь с IEnumerable как можно дольше для лучшей производительности. –

ответ

10

Согласно @Marc L'сообщению пользователя, вы можете попробовать это:

public static List<string> ReadInCSV(string absolutePath) { 
    List<string> result = new List<string>(); 
    string value; 
    using (TextReader fileReader = File.OpenText(absolutePath)) { 
     var csv = new CsvReader(fileReader); 
     csv.Configuration.HasHeaderRecord = false; 
     while (csv.Read()) { 
      for(int i=0; csv.TryGetField<string>(i, out value); i++) { 
       result.Add(value); 
      } 
     } 
    } 
    return result; 
} 
+0

@MarcL. что вы имеете в виду? – masinger

+0

Это дает ответ, который я изначально искал, поэтому я буду принимать это как ответ, но я думаю @MarcL. что CsvHelper не предназначен для файлов CSV, которые у меня есть. – Ayb4btu

+0

Вы знаете, что вы можете использовать библиотеку VB csv для анализа файла csv, правильно? вы можете ссылаться на него и использовать его так же, как если бы это была библиотека C#. – AgapwIesu

2

Вы близко. Дело не в том, что он пытается преобразовать строку в строку в строку. CsvHelper пытается сопоставить каждое поле в строке свойствам того типа, который вы ему даете, используя имена, указанные в строке заголовка. Кроме того, он не понимает, как это сделать с помощью IEnumerable типов (которые реализует string), поэтому он просто бросает, когда это авто-сопоставление попадает в эту точку при тестировании типа.


Это сложная задача для того, что вы делаете. Если ваш формат файла достаточно прост, который, как представляется, - это хорошо известный формат поля, ни экранированные, ни кавычки. Я не вижу причин, по которым вам нужно взять накладные расходы на импорте библиотеки. Вы должны иметь возможность перечислять значения по мере необходимости с System.IO.File.ReadLines() и String.Split().

//pseudo-code...you don't need CsvHelper for this 
IEnumerable<string> GetFields(string filepath) 
{ 
    foreach(string row in File.ReadLines(filepath)) 
    { 
    foreach(string field in row.Split(',')) yield return field; 
    } 
} 
+0

Итак, CsvHelper предназначен для обработки CSV-файлов с определенными столбцами и передачи их в пользовательский класс, который содержит параметры для этих столбцов? Возможно ли использовать CsvHelper в моей ситуации, или требуется ли повторение по каждому полю? – Ayb4btu

+0

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

9

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

var parser = new CsvParser(textReader); 
while(true) 
{ 
    string[] row = parser.Read(); 
    if(row == null) 
    { 
     break; 
    } 
} 

http://joshclose.github.io/CsvHelper/#reading-parsing

Update

Версия 3 имеет поддержку чтения и записи IEnumerable свойства.

+1

Любопытно: действительно ли это дает вам что-то, что вы еще не получили с помощью 'File.ReadAllLines()', что оправдывает стоимость добавления другой зависимости от библиотеки? Кроме того, не 'CsvParser'' IDisposable'? –

+1

Он разбивает линию на поля на основе RFC 4180, имеет некоторую конфигурацию для работы с нестандартными файлами и возвращается к обработке, как это делает Excel. Что делать, если в вашем поле есть '\ n'? 'ReadAllLines()' даст вам 2 строки, когда это всего лишь 1 строка CSV. –

+0

Я использую созданный вами csvhelper, и я хочу прочитать все данные csv в data reader.is возможно, поскольку я не могу найти какой-либо пример, в котором говорится, как конвертировать данные в устройство чтения данных –

3

Пожалуйста, попробуйте это. Это сработало для меня.

TextReader reader = File.OpenText(filePath); 
      CsvReader csvFile = new CsvReader(reader); 
      csvFile.Configuration.HasHeaderRecord = true; 
      csvFile.Read(); 
      var records = csvFile.GetRecords<Server>().ToList(); 

Сервер является классом сущности. Так я и создал.

public class Server 
    { 
     private string details_Table0_ProductName; 
     public string Details_Table0_ProductName 
     { 
      get 
      { 
       return details_Table0_ProductName; 
      } 
      set 
      { 
       this.details_Table0_ProductName = value; 
      } 
     } 

     private string details_Table0_Version; 
     public string Details_Table0_Version 
     { 
      get 
      { 
       return details_Table0_Version; 
      } 
      set 
      { 
       this.details_Table0_Version = value; 
      } 
     }  
    } 

 Смежные вопросы

  • Нет связанных вопросов^_^