14

我用来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;
        }
    }
}

我们想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 中动态排除类型字段?

如果有必要,我们可以处理生成的文件,但我不知道如何删除整个 CSV 列CsvHelper

4

5 回答 5

21

我最近需要通过确定在运行时包含哪些字段来获得类似的结果。这是我的方法:

  1. 创建一个映射文件,通过将枚举传入类构造函数来映射我在运行时需要哪些字段

    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;
            }
        }
    }
    
  2. 写出使用映射配置的记录

    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();
    }
    
于 2014-06-23T20:01:59.820 回答
9

像这样标记字段:

[CsvField( Ignore = true )]
public double ResultQuantity { get; private set; }

更新:没关系。我看到您想在运行时执行此操作,而不是编译时。对于可能犯同样错误的其他人,我会将其作为危险信号。

于 2013-04-16T21:19:02.860 回答
6

你可以这样做:

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);
    }
}

我们强制创建属性映射,然后对其进行修改,动态删除列。

于 2013-04-16T22:38:26.447 回答
5

我的代码也有类似的问题,我通过以下代码修复了它。

你可以这样做:

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);
    }
}
于 2019-08-16T09:48:20.113 回答
2

我还必须解决这个问题:我有几十个记录类型,它们有一个共同的基类和一个必须被所有人忽略的共同字段:

// Nothing special here
internal class MyClassMap<T> : ClassMap<T> where T : MyRecordBaseClass
{ 
    public MyClassMap()
    {
        AutoMap();
        Map( m => m.SOME_FIELD ).Ignore();
    }
} 

这部分通常有据可查,而不是动态部分。

但是一个类需要通过动态忽略不同的字段来特殊调味,虽然我可以创建一个单独的地图类,但这并没有达到我期望的更多这样的规模,所以我终于想出了如何去做适当地:

    ...
    // 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();
    }
    ...

这适用于 CsvHelper 版本 7.1.1 和 12.1.1。

于 2019-01-14T01:43:24.413 回答