使用CsvHelper从单个csv文件读取多个类
最近我一直在使用Josh Close'CsvHelper来解析CSV文件,我非常喜欢流利的api用于类映射.
I've been using Josh Close' CsvHelper a bit recently to parse CSV files, I quite like the fluent api for class mapping.
我正在尝试映射包含多种记录类型的csv文件,文件结构为
I'm trying to map a csv file which contains multiple record types, the file structure is
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字段-我真的很想能够做类似的事情
Is this something which can be handled by CsvHelper? I've writen a custom parser which basically works but all it really does is filter out the Header and Data fields for a specific class - I'd really like to be able to do something like
csv.Configuration.RegisterClassMap<Class1>();
csv.Configuration.RegisterClassMap<Class2>();
var data1 = csv.GetRecords<Class1>().ToList();
var data2 = csv.GetRecords<Class2>().ToList();
一次读取文件?这可能还是我使用了错误的解析器?
And read the file in one pass? Is this possible or am I using the wrong parser?
问候戴夫
有一种方法可以做到;您只需要手动执行即可.
There is a way to do this; you just have to do it manually.
- 您手动逐行手动读取csv文件
- 检查第一列的鉴别符,以表明您需要映射到Class对象.
- 检查第二列以映射到该类.
-
将整个行映射到该给定的类.
- You manually read the csv file row by row
- Inspect the first column for the discriminator that will indicate that you need to map to a Class object.
- Inspect the second column for the class to map to.
Map the entire row to that given class.
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;
}
}
}
}
}