在使用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);
答案 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))
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);
然后,我使用reader.BaseStream.Position = 0;
将位置设置回0,然后在保存文件后处置读取器。