如何使用 CSVHelper 在 CSV 中写入类的列表属性

发布于 2025-01-14 18:46:17 字数 773 浏览 3 评论 0原文

目前我有以下类结构

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 实现吗?还是我需要编写自己的实现?

Currently I have the following class structures

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

Now I want to write a CSV file which has a field "ID" which is a mix between the ID of the Foo and Bars ID and the rest should be the properties of the Bar object.

This are some example objects:

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}

Now the CSV writer should create a CSV looking like this:

ID;Prop1;Prop2;Prop3
01A;Red;Red;Green
01B;Yellow;Red;Red
02A;Green;Green;Red
02B;Red;Purple;Orange
02C;White;Black;Red

Is this possible with the CSVHelper or do I need to write my own implementation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

白馒头 2025-01-21 18:46:17

遗憾的是,您无法直接从单个对象创建多个 CSV 行。因此,您必须整理列表并将其写入 CSV 文件。

这是一个工作示例

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

Unfortunately you can not directly create multiple CSV lines from a single object. So you have to flatten your list and write these into a CSV file.

Here is a 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 = 
quot;{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();
    }
}
落花浅忆 2025-01-21 18:46:17

您只需要 writer 对象和嵌套的 for 循环。

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

You only need the writer object and for-loop nested.

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();
                    }
                    
                }
            }
        }
才能让你更想念 2025-01-21 18:46:17

我找到了一种更简单、更简单的做事方法:

我基本上创建了一个名为 CSVEntry 的新类,具有所需的属性,并循环遍历我的对象以生成所需的条目,然后使用 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);

            }

        }

    }

I have found a much easier and less complicated way of doing things:

I basically created a new Class called CSVEntry with the required properties and looped trough my opjects to generate the desired entry before writing them to a file with 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);

            }

        }

    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文