使用 CsvHelper 读取 CSV 文件后如何写入?

How to write a CSV file after reading it with CsvHelper?

在使用 CsvHelper nuget 包将其映射到列表后,我需要编写一个 HttpPostedFileBase csv(并保存)。但是,在使用 CsvHelper 映射之后,ContentLength 为 0,我最终保存了一个空的 .csv 文件。

CsvHelper 本身声明在使用 GetRecords<T>() 方法时不应使用 Read 方法。

        // 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;

但这没有用。尝试了我在 Whosebug 上找到的其他一些解决方案,但也没有用。我 "solved" 通过将同一个文件作为参数两次发送到控制器来解决这个问题。然后我将第一个与 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);

我不确定 GetRecords 是如何工作的,但它有可能将光标留在指向末尾的流上。

意思是你的保存序列在最后开始读取 InputStream,这导致没有数据可读。

所以你可以试试

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

编辑:

对于复制流的尝试,您只复制了对对象的引用,而不是对象本身。 要复制流数据,您需要使用 CopyTo(stream) 方法,该方法会将光标留在流的末尾,因此这里肯定需要查找。

问题是 CsvHelper:

using(var csvReader = new CsvReader(reader))

在 using 语句结束时,CsvReader 关闭 reader。然后当我尝试

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

reader.BaseStream.Position = 0; 

它抛出一个 NullReferenceException。我通过简单地覆盖 CsvReader:

解决了这个问题
using (var csvReader = new CsvReader(reader, true))

trueleaveOpen:

        // 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);

然后我使用reader.BaseStream.Position = 0;将位置设置回0,然后在保存文件后,处理reader。