这是我的原始代码,不使用CsvHelper写入CSV文件。
public static void Write(string file, List<PayRecord> payrecords) {
using(StreamWriter sw = new StreamWriter(file)) {
sw.WriteLine("EmployeeId,Gross,Tax,Net");
foreach(PayRecord c in payrecords) {
string line = string.Format("{0},{1},{2},{3}",
c.Id,
c.Gross,
c.Tax,
c.Net);
sw.WriteLine(line);
}
}
}
这是相同的代码,但这次使用了CsvHelper:
public static void Write(string file, List<PayRecord> payrecords)
{
using (StreamWriter sw = new StreamWriter(file))
using (CsvWriter cw = new CsvWriter(sw, CultureInfo.CurrentCulture))
{
cw.WriteHeader<PayRecord>();
foreach (var c in payrecords)
{
string line = string.Format("{0},{1},{2},{3}",
c.Id,
c.Gross,
c.Tax,
c.Net);
cw.WriteRecord(line);
}
}
}
但我遇到了一些例外,比如:
Unhandled exception. CsvHelper.Configuration.ConfigurationException: Types that inherit IEnumerable cannot be auto mapped. Did you accidentally call GetRecord or WriteRecord which acts on a single record instead of calling GetRecords or WriteRecords which acts on a list of records?
at CsvHelper.CsvWriter.WriteRecord[T](T record)
以及:
Unhandled exception. System.ArgumentNullException: Value cannot be null. (Parameter 'source')
at System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument)
at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source)
at CsvHelper.Configuration.ClassMap.AutoMapConstructorParameters(ClassMap map, CsvContext context, LinkedList`1 mapParents, Int32 indexStart)
at CsvHelper.Configuration.ClassMap.AutoMapConstructorParameters(ClassMap map, CsvContext context, LinkedList`1 mapParents, Int32 indexStart)
at CsvHelper.Configuration.ClassMap.AutoMap(CsvContext context)
at CsvHelper.CsvContext.AutoMap(Type type)
at CsvHelper.CsvWriter.WriteHeader(Type type)
at CsvHelper.CsvWriter.WriteHeader[T]()
出什么事了?
1条答案
按热度按时间yptwkmov1#
您正尝试将
string
写入记录。cw.WriteRecord(line);
我不可能重现您的
ArgumentNullException
,但我知道即使修复了这个问题,您的代码仍然无法工作。上面的代码将抛出一个
CsvHelper.Configuration.ConfigurationException
,因为string
被分类为单个字段&CsvHelper.WriteRecord
更多地用于类,而不是string
。其次,
CsvWriter.WriteHeader
不会将“光标”移动到下一行,因此您需要使用CsvWriter.NextRecord()
,否则您的数据将与标题位于同一行。下面的代码可以工作:
但是,最好不要手动编写头文件,使用
CsvHelper.WriteRecords
并传递整个对象集合,如下所示。这使得正确使用
CsvHelper.WriteRecords
的代码更小、更干净、更高效,同时还能编写正确的头文件。这是 * 更好 *:
"更好"
要在不阻塞主线程的情况下执行I/O操作(写入CSV文件),请使用
CsvHelper.WriteRecordsAsync
,使用await using
不阻塞资源清理,并使您的方法async
能够执行await
调用。我还将使用
ICollection<PayRecord>
,这样,如果您将List<PayRecord>
更改为任何其他实现ICollection
的类型,则不需要更改方法。上面的代码甚至可以处理
null
字段、null
对象,并且如果集合是null
,还会抛出异常(否则,CsvHelper将抛出异常)。希望能有所帮助!