2016-12-02 94 views
4

假设我有一个大的csv文件,我想要读取,修改和回写。也许我想将字段分隔符从逗号更改为制表符。也许我想将引号字符从'改为',或者可能是我想为第一列中的每个值添加一个加号,由于文件很大,我不想一次加载到内存中,我想读它通过记录记录更改csv文件,使用动态映射进行读取和写入

所以我写这样的代码:

var inPath = @"infile.txt"; 
var outPath = @"outfile.txt"; 

CsvConfiguration readCf = GetReadConfiguration(); 
CsvConfiguration writeCf = GetWriteConfiguration(); 

using (var streamin = new FileStream(inPath, FileMode.Open)) 
using (var streamReader = new StreamReader(streamin)) 
{ 
    using (var csvReader = new CsvReader(streamReader, readCf)) 
    using (var csvWriter = new CsvWriter(new StreamWriter(outPath), writeCf)) 
    { 
     while (csvReader.Read()) 
     { 
      var currentRecord = csvReader.GetRecord<dynamic>(); 
      UpdateRecord(currentRecord); 
      csvWriter.WriteRecord(currentRecord); 
     } 
    } 
} 

这种失败在运行时,出现以下错误:

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?

。注意,没有什么有趣的事发生在UpdateRecord,其实这一行上面可以完全评论ou吨。

发生什么事是GetRecord返回ExpandoObject,然后WriteRecord扼流器在此对象上。

使这项工作的最佳方式是什么?

更新 只是所以很清楚:我充分认识到,我得到这个错误是因为CSVHelper不支持ExpandoObject S表示WriteRecord电话。我正在寻找建议,以便完成此项工作。

+0

错误是告诉你使用GetRecords(复数)而不是单数。我的意思是它暗示它。你尝试过吗? – CodingYoshi

+0

@CodingYoshi,不,我不需要。 –

+0

看看Mar L的答案[这里](http://stackoverflow.com/questions/33294738/read-all-values-from-csv-into-a-list-using-csvhelper),看看是否有帮助你。 – CodingYoshi

回答

4

this commit中似乎增加了写入ExpandoObject的能力。

请注意,这不是最新的Nuget版本(截至编写时为2.16.3),而是下一个3.x版本。如果这是您从github获得最新测试版的选项并使用它。

如果这样做,请注意,您必须在每个WriteRecord之后致电NextRecord。在2.16.3 CVSHelper会为你调用它,所以这是一个突破API的变化

+0

旧版本给了我'CsvConfigurationException:继承IEnumerable的类型不能被自动映射。您是否意外地调用了GetRecord或WriteRecord,它只作用于单个记录,而不是调用GetRecords或WriteRecords作用于记录列表?'和新版本(3.0)给了我'CsvTypeConverterException:转换IEnumerable类型不支持单个字段。如果您想这样做,请创建您自己的ITypeConverter,并通过调用AddConverter将其注册到TypeConverterFactory中。 –