【问题标题】:How to write a CSV file after reading it with CsvHelper?使用 CsvHelper 读取后如何编写 CSV 文件?
【发布时间】:2019-07-01 09:09:34
【问题描述】:

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

【问题讨论】:

  • 您的保存示例看起来不完整..如果您已阅读到流的末尾,则需要回到开头 - 我认为重点是写出您的映射版本而不是只需保存流..

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


【解决方案1】:

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

意味着您的保存序列最后开始读取 InputStream,这导致没有数据可读取。

所以你可以试试

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

编辑:

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

【讨论】:

    【解决方案2】:

    问题是 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);
    

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

    【讨论】:

      猜你喜欢
      • 2021-10-02
      • 1970-01-01
      • 2021-10-03
      • 1970-01-01
      • 1970-01-01
      • 2014-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多