2016-12-02 3 views
4

Предположим, у меня есть большой файл csv, который я бы хотел прочитать, изменить и написать. Возможно, я хочу изменить разделитель полей с запятой на вкладку. Возможно, я хочу изменить символ котировки от «до». Может быть, я хочу добавить знак плюса к каждому значению в первом столбце. Поскольку файл большой, я не хочу загружать его в память сразу, Я хотел бы прочитать его запись записьюИзменение файла csv, чтение и запись с динамическим сопоставлением

Так я пишу такой код:.

var inPath = @"infile.txt"; 
var outPath = @"outfile.txt"; 

CsvConfiguration readCf = GetReadConfiguration(); 
CsvConfiguration writeCf = GetWriteConfiguration(); 

using (var streamin = new FileStream(inPath, FileMode.Open)) 
using (var streamReader = new StreamReader(streamin)) 
{ 
    using (var csvReader = new CsvReader(streamReader, readCf)) 
    using (var csvWriter = new CsvWriter(new StreamWriter(outPath), writeCf)) 
    { 
     while (csvReader.Read()) 
     { 
      var currentRecord = csvReader.GetRecord<dynamic>(); 
      UpdateRecord(currentRecord); 
      csvWriter.WriteRecord(currentRecord); 
     } 
    } 
} 

Это терпит неудачу во время выполнения со следующей ошибкой:

Types that inherit IEnumerable cannot be auto mapped. Did you accidentally call GetRecord or WriteRecord which acts on a single record instead of calling GetRecords or WriteRecords which acts on a list of records?

Заметим, что ничего интересного не происходит в UpdateRecord, на самом деле эта строка выше может быть полностью прокомментирована ou т.

Что происходит, так это то, что GetRecord возвращает ExpandoObject, а затем WriteRecord дроссели на этом объекте.

Каков наилучший способ сделать эту работу?

Update Просто так ясно: я полностью понимаю, что я получаю эту ошибку, потому что CSVHelper не поддерживает ExpandoObject с для WriteRecord вызова. Я ищу предложения, чтобы облегчить эту работу.

+0

Ошибка говорит вам использовать GetRecords (множественное число) вместо единственного числа. Я имею в виду, что это намекает. Вы попробовали это? – CodingYoshi

+0

@CodingYoshi, нет, это не то, что мне нужно. –

+0

Посмотрите на ответ Мар L [здесь] (http://stackoverflow.com/questions/33294738/read-all-values-from-csv-into-a-list-using-csvhelper) и посмотрите, поможет ли это вам. – CodingYoshi

ответ

4

Похоже, что способность писать ExpandoObject добавляется в this commit.

Обратите внимание, что это не последняя версия nuget (2.16.3 на момент написания), а для следующей версии 3.x. Если это вариант, вы получаете последнюю бета-версию от github и используете это.

Если вы это сделаете, обратите внимание, что вам необходимо позвонить NextRecord после каждого WriteRecord. В 2.16.3 CVSHelper назвал бы это для вас, так что это немного нарушает API API.

+0

Старая версия дала мне 'CsvConfigurationException: типы, наследующие IEnumerable, не могут быть автоматически сопоставлены. Вы случайно вызвали GetRecord или WriteRecord, которые действуют на одну запись, вместо того, чтобы вызывать GetRecords или WriteRecords, которые действуют в списке записей?'и новая версия (3.0) дает мне' CsvTypeConverterException: Преобразование типов IEnumerable не поддерживается для одного поля. Если вы хотите это сделать, создайте свой собственный ITypeConverter и зарегистрируйте его в TypeConverterFactory, вызвав AddConverter. ' –