如何用CSV helper只写选定的类字段
本文关键字:字段 何用 CSV helper | 更新日期: 2023-09-27 18:09:36
我使用CsvHelper
来读写CSV文件,它很棒,但我不明白如何只写选定的类型字段。
假设我们有:
using CsvHelper.Configuration;
namespace Project
{
public class DataView
{
[CsvField(Name = "N")]
public string ElementId { get; private set; }
[CsvField(Name = "Quantity")]
public double ResultQuantity { get; private set; }
public DataView(string id, double result)
{
ElementId = id;
ResultQuantity = result;
}
}
}
和我们想要排除"Quantity" CsvField
从结果CSV文件,我们目前通过以下方式生成:
using (var myStream = saveFileDialog1.OpenFile())
{
using (var writer = new CsvWriter(new StreamWriter(myStream)))
{
writer.Configuration.Delimiter = ''t';
writer.WriteHeader(typeof(ResultView));
_researchResults.ForEach(writer.WriteRecord);
}
}
我可以使用什么来动态地从CSV中排除类型字段?
如果有必要,我们可以处理结果文件,但我不知道如何使用CsvHelper
删除整个CSV列。
我最近需要通过确定在运行时包含哪些字段来实现类似的结果。这是我的方法:
-
创建一个映射文件,通过在类构造函数中传递枚举来映射运行时需要的字段
public sealed class MyClassMap : CsvClassMap<MyClass> { public MyClassMap(ClassType type) { switch (type) { case ClassType.TypeOdd Map(m => m.Field1); Map(m => m.Field3); Map(m => m.Field5); break; case ClassType.TypeEven: Map(m => m.Field2); Map(m => m.Field4); Map(m => m.Field6); break; case ClassType.TypeAll: Map(m => m.Field1); Map(m => m.Field2); Map(m => m.Field3); Map(m => m.Field4); Map(m => m.Field5); Map(m => m.Field6); break; } } }
-
写出使用映射配置的记录
using (var memoryStream = new MemoryStream()) using (var streamWriter = new StreamWriter(memoryStream)) using (var csvWriter = new CsvWriter(streamWriter)) { csvWriter.Configuration.RegisterClassMap(new MyClassMap(ClassType.TypeOdd)); csvWriter.WriteRecords(records); streamWriter.Flush(); return memoryStream.ToArray(); }
像这样标记字段:
[CsvField( Ignore = true )]
public double ResultQuantity { get; private set; }
更新:无所谓。我知道您希望在运行时而不是编译时执行此操作。我将把这个作为警告,提醒其他可能犯同样错误的人。
你可以这样做:
using (var myStream = saveFileDialog1.OpenFile())
{
using (var writer = new CsvWriter(new StreamWriter(myStream)))
{
writer.Configuration.AttributeMapping(typeof(DataView)); // Creates the CSV property mapping
writer.Configuration.Properties.RemoveAt(1); // Removes the property at the position 1
writer.Configuration.Delimiter = "'t";
writer.WriteHeader(typeof(DataView));
_researchResults.ForEach(writer.WriteRecord);
}
}
我们强制创建属性映射,然后修改它,动态地删除列
我的代码也有类似的问题,我用下面的代码修复了它。
你可以这样做:
var ignoreQuantity = true;
using (var myStream = saveFileDialog1.OpenFile())
{
using (var writer = new CsvWriter(new StreamWriter(myStream)))
{
var classMap = new DefaultClassMap<DataView>();
classMap.AutoMap();
classMap.Map(m => m.ResultQuantity).Ignore(ignoreQuantity)
writer.Configuration.RegisterClassMap(classMap);
writer.Configuration.Delimiter = "'t";
writer.WriteHeader(typeof(DataView));
_researchResults.ForEach(writer.WriteRecord);
}
}
我还必须解决这个问题:我有几十个记录类型,有一个共同的基类和一个共同的字段,必须被所有它们忽略:
// Nothing special here
internal class MyClassMap<T> : ClassMap<T> where T : MyRecordBaseClass
{
public MyClassMap()
{
AutoMap();
Map( m => m.SOME_FIELD ).Ignore();
}
}
这部分通常有很好的文档,而不是动态部分。
但是一个类需要通过动态忽略不同的字段来进行特殊处理,尽管我可以创建一个单独的map类,但这并不能满足我所期望的更多,所以我最终找到了正确的方法:
...
// special processing for *one* record type
csvwriter.Configuration.RegisterClassMap<MyClassMap<ONE_RECORD_TYPE>>();
if (ShouldIgnore)
{
var map = csvwriter.Configuration.Maps.Find<ONE_RECORD_TYPE>();
map.Map( m => m.SOME_OTHER_FIELD ).Ignore();
}
...