如何使用 CSVHelper 在 CSV 中写入 class 的列表属性
How to write the list attribute of a class in CSV using CSVHelper
目前我有以下class个结构
class Foo{
int FooID {get;set;}
List<Bar> Bars {get;set;};
}
class Bar{
int BarID {get;set;}
string BarProperty1 {get;set;}
string BarProperty2 {get;set;}
string BarProperty3 {get;set;}
}
现在我想写一个 CSV 文件,它有一个字段“ID”,它是 Foo 的 ID 和 Bars ID 的混合,其余的应该是 Bar 对象的属性。
这是一些示例对象:
Foo01 ID = 01
List bars = {A, Red, Red, Green; B, Yellow, Red, Red}
Foo02 ID = 02
List bars = {A, Green, Green, Red; B, Red, Purple, Orange; C, White, Black, Red}
现在 CSV 编写器应该创建如下所示的 CSV:
ID;Prop1;Prop2;Prop3
01A;Red;Red;Green
01B;Yellow;Red;Red
02A;Green;Green;Red
02B;Red;Purple;Orange
02C;White;Black;Red
使用 CSVHelper 是否可行,还是我需要编写自己的实现?
遗憾的是,您无法直接从单个对象创建多个 CSV 行。因此,您必须将列表展平并将它们写入 CSV 文件。
这是一个working example:
public class BarMap : ClassMap<Bar>
{
public BarMap()
{
Map(bar => bar.BarID).Name("Id");
Map(bar => bar.BarProperty1).Name("Prop1");
Map(bar => bar.BarProperty2).Name("Prop2");
Map(bar => bar.BarProperty3).Name("Prop3");
}
}
string content = null;
using (var memory = new MemoryStream())
using (var writer = new StreamWriter(memory))
using (var csv = new CsvWriter(writer, CultureInfo.GetCultureInfo("en")))
{
csv.Context.RegisterClassMap<BarMap>();
// Flatten nested collections into one list
var bars = foos
// Would be less typing probably if using AutoMapper to create new instances.
.SelectMany(foo => foo.Bars.Select(bar => new Bar { BarID = $"{foo.FooID}{bar.BarID}", BarProperty1 = bar.BarProperty1, BarProperty2 = bar.BarProperty2, BarProperty3 = bar.BarProperty3 }));
csv.WriteRecords(bars);
writer.Flush();
memory.Position = 0;
using (var reader = new StreamReader(memory))
{
content = reader.ReadToEnd();
}
}
您只需要 writer 对象和 for-loop 嵌套。
public static void Main()
{
// set up
var bars1 = new List<Bar>();
bars1.Add(new Bar() { BarID = 1, BarProperty1 = "Red", BarProperty2 = "Green", BarProperty3 = "Green" });
bars1.Add(new Bar() { BarID = 2, BarProperty1 = "White", BarProperty2 = "Green", BarProperty3 = "Black" });
var bars2 = new List<Bar>();
bars2.Add(new Bar() { BarID = 1, BarProperty1 = "Pink", BarProperty2 = "Green", BarProperty3 = "Green" });
bars2.Add(new Bar() { BarID = 2, BarProperty1 = "White", BarProperty2 = "Green", BarProperty3 = "Black" });
bars2.Add(new Bar() { BarID = 2, BarProperty1 = "Cyan", BarProperty2 = "Green", BarProperty3 = "Black" });
var foo1 = new Foo() { FooID = 1, Bars = bars1 };
var foo2 = new Foo() { FooID = 2, Bars = bars2 };
var foos = new List<Foo>() { foo1, foo2 };
// write CSV
using (var writer = new StreamWriter("file.csv"))
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
writer.WriteLine("Id,Prop1,Prop2,Prop3");
foreach (var foo in foos)
{
foreach (var bar in foo.Bars)
{
writer.Write(foo.FooID);
csv.WriteRecord(bar);
csv.NextRecord();
}
}
}
}
我发现了一种更简单、更简单的做事方式:
我基本上创建了一个名为 CSVEntry 的新 Class,它具有所需的属性,并循环遍历我的对象以生成所需的条目,然后再使用 CSVHelper 将它们写入文件。
foreach (Foo foo in foos)
{
foreach (Bar bar in foo.bars)
{
CSVEntry CSVEntry = new CSVEntry();
CSVEntry.id = (foo.id + bar.id);
CSVEntry.property1 = bar.property1;
CSVEntry.property2 = bar.property2;
CSVEntry.property3 = bar.property3;
CSVEntries.Add(CSVEntry);
}
}
public static void writeCSVfile(List<CSVEntry> CSVEntries, String csvPath)
{
using (var streamedWriter = new StreamWriter(csvPath))
{
using (var csvWriter = new CsvWriter(streamedWriter, System.Globalization.CultureInfo.CurrentUICulture))
{
csvWriter.WriteRecords(CSVEntries);
}
}
}
目前我有以下class个结构
class Foo{
int FooID {get;set;}
List<Bar> Bars {get;set;};
}
class Bar{
int BarID {get;set;}
string BarProperty1 {get;set;}
string BarProperty2 {get;set;}
string BarProperty3 {get;set;}
}
现在我想写一个 CSV 文件,它有一个字段“ID”,它是 Foo 的 ID 和 Bars ID 的混合,其余的应该是 Bar 对象的属性。
这是一些示例对象:
Foo01 ID = 01
List bars = {A, Red, Red, Green; B, Yellow, Red, Red}
Foo02 ID = 02
List bars = {A, Green, Green, Red; B, Red, Purple, Orange; C, White, Black, Red}
现在 CSV 编写器应该创建如下所示的 CSV:
ID;Prop1;Prop2;Prop3
01A;Red;Red;Green
01B;Yellow;Red;Red
02A;Green;Green;Red
02B;Red;Purple;Orange
02C;White;Black;Red
使用 CSVHelper 是否可行,还是我需要编写自己的实现?
遗憾的是,您无法直接从单个对象创建多个 CSV 行。因此,您必须将列表展平并将它们写入 CSV 文件。
这是一个working example:
public class BarMap : ClassMap<Bar>
{
public BarMap()
{
Map(bar => bar.BarID).Name("Id");
Map(bar => bar.BarProperty1).Name("Prop1");
Map(bar => bar.BarProperty2).Name("Prop2");
Map(bar => bar.BarProperty3).Name("Prop3");
}
}
string content = null;
using (var memory = new MemoryStream())
using (var writer = new StreamWriter(memory))
using (var csv = new CsvWriter(writer, CultureInfo.GetCultureInfo("en")))
{
csv.Context.RegisterClassMap<BarMap>();
// Flatten nested collections into one list
var bars = foos
// Would be less typing probably if using AutoMapper to create new instances.
.SelectMany(foo => foo.Bars.Select(bar => new Bar { BarID = $"{foo.FooID}{bar.BarID}", BarProperty1 = bar.BarProperty1, BarProperty2 = bar.BarProperty2, BarProperty3 = bar.BarProperty3 }));
csv.WriteRecords(bars);
writer.Flush();
memory.Position = 0;
using (var reader = new StreamReader(memory))
{
content = reader.ReadToEnd();
}
}
您只需要 writer 对象和 for-loop 嵌套。
public static void Main()
{
// set up
var bars1 = new List<Bar>();
bars1.Add(new Bar() { BarID = 1, BarProperty1 = "Red", BarProperty2 = "Green", BarProperty3 = "Green" });
bars1.Add(new Bar() { BarID = 2, BarProperty1 = "White", BarProperty2 = "Green", BarProperty3 = "Black" });
var bars2 = new List<Bar>();
bars2.Add(new Bar() { BarID = 1, BarProperty1 = "Pink", BarProperty2 = "Green", BarProperty3 = "Green" });
bars2.Add(new Bar() { BarID = 2, BarProperty1 = "White", BarProperty2 = "Green", BarProperty3 = "Black" });
bars2.Add(new Bar() { BarID = 2, BarProperty1 = "Cyan", BarProperty2 = "Green", BarProperty3 = "Black" });
var foo1 = new Foo() { FooID = 1, Bars = bars1 };
var foo2 = new Foo() { FooID = 2, Bars = bars2 };
var foos = new List<Foo>() { foo1, foo2 };
// write CSV
using (var writer = new StreamWriter("file.csv"))
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
writer.WriteLine("Id,Prop1,Prop2,Prop3");
foreach (var foo in foos)
{
foreach (var bar in foo.Bars)
{
writer.Write(foo.FooID);
csv.WriteRecord(bar);
csv.NextRecord();
}
}
}
}
我发现了一种更简单、更简单的做事方式:
我基本上创建了一个名为 CSVEntry 的新 Class,它具有所需的属性,并循环遍历我的对象以生成所需的条目,然后再使用 CSVHelper 将它们写入文件。
foreach (Foo foo in foos)
{
foreach (Bar bar in foo.bars)
{
CSVEntry CSVEntry = new CSVEntry();
CSVEntry.id = (foo.id + bar.id);
CSVEntry.property1 = bar.property1;
CSVEntry.property2 = bar.property2;
CSVEntry.property3 = bar.property3;
CSVEntries.Add(CSVEntry);
}
}
public static void writeCSVfile(List<CSVEntry> CSVEntries, String csvPath)
{
using (var streamedWriter = new StreamWriter(csvPath))
{
using (var csvWriter = new CsvWriter(streamedWriter, System.Globalization.CultureInfo.CurrentUICulture))
{
csvWriter.WriteRecords(CSVEntries);
}
}
}