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

时间:2019-07-01 09:09:34

标签: c# .net csvhelper system.io.file

在使用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;

但这没用。尝试了一些我在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 个答案:

答案 0 :(得分:1)

我不确定GetRecords的工作方式,但可能会将光标留在指向末尾的流上。

就您的保存顺序而言,您从末尾开始读取InputStream,这导致没有数据可读取。

所以您可以尝试

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

编辑:

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

答案 1 :(得分:1)

问题是CsvHelper:

using(var csvReader = new CsvReader(reader))

在using语句的结尾,CsvReader关闭阅读器。然后,当我尝试

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,然后在保存文件后处置读取器。

相关问题