写入可枚举到csv文件

时间:2014-08-14 10:43:43

标签: csv csvhelper

我确信它非常简单,但我正在努力弄清楚如何使用CSVHelper将数组写入文件。

我有一个班级,例如

public class Test
{
public Test()
{
data = new float[]{0,1,2,3,4};
}
 public float[] data{get;set;}
}

我希望将数据与每个数组值一起写入单独的单元格中。我在下面有一个自定义转换器,而是为一个单元格提供其中的所有值。

我做错了什么?

public class DataArrayConverter<T> : ITypeConverter
{
    public string ConvertToString(TypeConverterOptions options, object value)
    {
        var data = (T[])value;

       var s = string.Join(",", data);

    }

    public object ConvertFromString(TypeConverterOptions options, string text)
    {
        throw new NotImplementedException();
    }

    public bool CanConvertFrom(Type type)
    {
        return type == typeof(string);
    }

    public bool CanConvertTo(Type type)
    {
        return type == typeof(string);
    }
}

2 个答案:

答案 0 :(得分:1)

不幸的是,它并没有像那样工作。由于您在转换器中返回,,它将引用该字段,因为它是单个字段的一部分。

目前,实现目标的唯一方法是手动编写,这并不太可怕。

foreach( var test in list )
{
    foreach( var item in test.Data )
    {
        csvWriter.WriteField( item );
    }

    csvWriter.NextRecord();
}

<强>更新

版本3支持读取和编写IEnumerable属性。

答案 1 :(得分:1)

要进一步详细了解 Josh Close 的答案,在此处您需要执行以下操作:编写最新版本(高于3.0的版本)的任何IEnumerable(包括数组和通用列表) CsvHelper!


这里是被测课程:

public class Test
{
    public int[] Data { get; set; }

    public Test()
    {
        Data = new int[] { 0, 1, 2, 3, 4 };
    }
}

以及显示如何保存的方法:

static void Main()
{
    using (var writer = new StreamWriter("db.csv"))
    using (var csv = new CsvWriter(writer))
    {
        var list = new List<Test>
        {
            new Test()
        };
        csv.Configuration.HasHeaderRecord = false;
        csv.WriteRecords(list);
        writer.Flush();
    }
}

此处的重要配置为csv.Configuration.HasHeaderRecord = false;。只有使用此配置,您才能看到csv文件中的数据。

更多详细信息可以在CsvHelper的相关unit test cases中找到。


如果您正在寻找一种解决方案,用于存储类型为IEnumerable的属性,其中元素的数量不同,以下示例可能会有所帮助:

using CsvHelper;
using CsvHelper.Configuration;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace CsvHelperSpike
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var writer = new StreamWriter("db.csv"))
            using (var csv = new CsvWriter(writer))
            {
                csv.Configuration.Delimiter = ";";
                var list = new List<AnotherTest>
                {
                    new AnotherTest("Before String") { Tags = new List<string> { "One", "Two", "Three" }, After="After String" },
                    new AnotherTest("This is still before") {After="after again", Tags=new List<string>{ "Six", "seven","eight", "nine"} }
                };
                csv.Configuration.RegisterClassMap<TestIndexMap>();
                csv.WriteRecords(list);
                writer.Flush();
            }

            using(var reader = new StreamReader("db.csv"))
            using(var csv = new CsvReader(reader))
            {
                csv.Configuration.IncludePrivateMembers = true;
                csv.Configuration.RegisterClassMap<TestIndexMap>();
                var result = csv.GetRecords<AnotherTest>().ToList();
            }
        }

        private class AnotherTest
        {
            public string Before { get; private set; }
            public string After { get; set; }
            public List<string> Tags { get; set; }

            public AnotherTest() { }

            public AnotherTest(string before)
            {
                this.Before = before;
            }
        }

        private sealed class TestIndexMap : ClassMap<AnotherTest>
        {
            public TestIndexMap()
            {
                Map(m => m.Before).Index(0);
                Map(m => m.After).Index(1);
                Map(m => m.Tags).Index(2);
            }
        }
    }
}

通过使用ClassMap,可以再次启用HasHeaderRecord(默认)。这里要特别注意,只有当元素数量不同的集合是最后一个属性时,此解决方案才有效。否则,集合需要具有固定数量的元素,并且ClassMap需要进行相应的调整。

此示例还显示了如何使用private set处理属性。为此,使用csv.Configuration.IncludePrivateMembers = true;配置并在类上使用默认构造函数很重要。