【问题标题】:Reading multiple classes from single csv file using CsvHelper使用 CsvHelper 从单个 csv 文件中读取多个类
【发布时间】:2015-12-03 03:38:55
【问题描述】:

我最近一直在使用 Josh Close 的 CsvHelper 来解析 CSV 文件,我非常喜欢用于类映射的 fluent api。

我正在尝试映射一个包含多种记录类型的 csv 文件,文件结构是

C,Comment,Timestamp
I,Class1,Header1,Header2
D,Class1,Data1,Data2
D,Class1,Data1,Data2
...
I,Class2,Header1,Header2,Header3
D,Class2,Data1,Data2,Data3
D,Class2,Data1,Data2,Data3
...
C,Checksum

这是 CsvHelper 可以处理的事情吗?我编写了一个自定义解析器,它基本上可以工作,但它真正做的只是过滤掉特定类的 Header 和 Data 字段 - 我真的很想能够做类似的事情

csv.Configuration.RegisterClassMap<Class1>();
csv.Configuration.RegisterClassMap<Class2>();

var data1 = csv.GetRecords<Class1>().ToList();             
var data2 = csv.GetRecords<Class2>().ToList();

并一次性读取文件?这是可能的还是我使用了错误的解析器?

问候 戴夫

【问题讨论】:

  • 40 年来我一直在解析这样的文本文件。如果我无法解析文件,没有人可以。我可以通过单次通过多种方式完成此操作。您必须使用不使用标题行的方法,因为您有多个具有不同标题的部分,并且每个部分可能包含不同数量的列。您需要使用 GroupBy 对前两列(类型 [C,I,D] 和类)上的数据进行排序。
  • 这并没有真正回答问题,CsvHelper 可以解析这个文件吗?
  • 您可能不再需要这方面的帮助,但是您如何知道哪条记录应该映射到哪个类?例如,所有行的长度是否不同,是否有鉴别列等?
  • 嗨@drneel,是的,有一个鉴别器列。第二列是类类型。第一个是行类型(I是headers,D是data)

标签: c# csvhelper


【解决方案1】:

有办法做到这一点;你只需要手动完成。

  1. 您手动逐行读取 csv 文件
  2. 检查第一列的判别器,这将表明您需要映射到 Class 对象。
  3. 检查要映射到的类的第二列。
  4. 将整行映射到给定的类。

    public static void ReadMultiClassCsv()
    {
        var class1Data = new List<Class1>();
        var class2Data = new List<Class2>();
    
        using (StreamReader reader = File.OpenText(@"C:\filename.csv"))
        using (var csvReader = new CsvReader(reader))
        {
            //1.  You manually read the csv file row by row
            while (csvReader.Read())
            {
                var discriminator = csvReader.GetField<string>(0);
    
                //2.  Inspect the first column for the discriminator that will indicate that you need to map to a Class object.
                if (discriminator == "D")
                {
                    var classType = csvReader.GetField<string>(1);
    
                    //3.  Inspect the second column for the class to map to.
                    switch (classType)
                    {
                        //4.  Map the entire row to that given class.
                        case "Class1":
                            class1Data.Add(csvReader.GetRecord<Class1>());
                            break;
                        case "Class2":
                            class2Data.Add(csvReader.GetRecord<Class2>());
                            break;
                        default:
                            break;
                    }
                }
            }
        }
    }
    

【讨论】:

  • 感谢您的回答。我猜类映射需要基于索引。这是正确的还是我实际上可以有一个带有名称映射的类映射?
  • 我将上述问题发布到github.com/JoshClose/CsvHelper/issues/441。得到了 Josh 的回复,其中包含代码示例来完成此操作。不过,这可以在版本 3 中完成。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-03
  • 2021-10-02
  • 1970-01-01
  • 2017-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多