Как написать файл CSV после чтения его с помощью CsvHelper? - PullRequest
1 голос
/ 01 июля 2019

Мне нужно написать HttpPostedFileBase csv (и сохранить его) после сопоставления его со списком с помощью пакета nuget CsvHelper. Однако после сопоставления с помощью CsvHelper значение ContentLength равно 0, и в итоге я сохраняю пустой файл .csv.

CsvHelper сам утверждает, что метод Read не должен использоваться при использовании метода GetRecords<T>().

        // Summary:
        //     Gets all the records in the CSV file and converts each to System.Type T. The
        //     Read method should not be used when using this.
        //
        // Type parameters:
        //   T:
        //     The System.Type of the record.
        //
        // Returns:
        //     An System.Collections.Generic.IEnumerable`1 of records.
        public virtual IEnumerable<T> GetRecords<T>();

Я попытался поместить его в переменную копирования:

HttpPostedFileBase csvCopy = csvFile;

Но это не сработало. Попробовал некоторые другие решения, которые я нашел в stackoverflow, которые тоже не работали. Я «решил» эту проблему, дважды отправив один и тот же файл на контроллер в качестве параметра. Затем я использую первый с CsvHelper, и я читаю и сохраняю другой.

 public async Task<ActionResult> ImportCSV(HttpPostedFileBase csvFile, HttpPostedFileBase csvFileCopy)

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

Отображение в список:

using(var reader = new StreamReader(csvFile.InputStream)) {
   using(var csvReader = new CsvReader(reader)) {
    csvReader.Configuration.RegisterClassMap(new CSVModelMap(mapDictionary));
    csvReader.Configuration.BadDataFound = null;
    csvReader.Configuration.HeaderValidated = null;
    csvReader.Configuration.MissingFieldFound = null;
    importData = csvReader.GetRecords<CSVModel>().ToList();    
   }
 }

Сохранение:

var fileName = serverPath + "\\" + hashedFileName;
CheckIfDirectoryExists(serverPath);
var reader = new StreamReader(csvFile.InputStream);
var csvContent = await reader.ReadToEndAsync();
File.WriteAllText(fileName, csvContent);

Ответы [ 2 ]

1 голос
/ 01 июля 2019

Проблема была в CsvHelper:

using(var csvReader = new CsvReader(reader))

В конце оператора использования CsvReader закрывает читатель. Затем, когда я пытаюсь

csvFile.InputStream.Seek(0, SeekOrigin.Begin);

или

reader.BaseStream.Position = 0; 

бросает NullReferenceException. Я решил это, просто переопределив CsvReader:

using (var csvReader = new CsvReader(reader, true))

true являющийся leaveOpen:

        // Summary:
        //     Creates a new CSV reader using the given System.IO.TextReader.
        //
        // Parameters:
        //   reader:
        //     The reader.
        //
        //   leaveOpen:
        //     true to leave the reader open after the CsvReader object is disposed, otherwise
        //     false.
        public CsvReader(TextReader reader, bool leaveOpen);

Затем я устанавливаю позицию обратно на 0, используя reader.BaseStream.Position = 0;, а затем после сохранения файла утилизирую читатель.

1 голос
/ 01 июля 2019

Я не уверен, как работает GetRecords, но может быть вероятность, что он оставит курсор на потоке, направленном к концу.

Это означает, что в последовательности сохранения вы начинаете читать InputStream в конце, что приводит к отсутствию данных для чтения.

Так что вы можете попробовать

csvFile.InputStream.Seek(0, SeekOrigin.Begin)

EDIT:

Для вашей попытки скопировать поток вы копируете только ссылку на объект, а не сам объект. Чтобы скопировать данные потока, вам нужно будет использовать метод CopyTo(stream), который оставит курсор в конце потока, поэтому поиск здесь обязательно необходим.

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