将字符串csv转换为对象列表

时间:2016-03-09 19:32:04

标签: c# string parsing csv

我有以下刺痛

const string csv = "Foo1,Foo2,Foo3,Foo4,Foo5,Foo6,Ping Pong\n" +
                   "2016-02-29,1437.530029,1445.839966,1433.77002,1436.930054,34016300,1436.930054\n" +
                   "2016-02-25,1431.439941,1431.439941,1421.280029,1426.97998,78076500,1426.97998\n" +
                   "2016-02-24,1430.459961,1432.430054,1417.449951,1419.790039,29049900,1419.790039\n";

如何将其转换为List<Model>

public class Model
{
    public string Foo1 { get; set; }
    public string Foo2 { get; set; }
    public string Foo3 { get; set; }
    public string Foo4 { get; set; }
    public string Foo5 { get; set; }
    public string Foo6 { get; set; }
    public string Ping_Pong { get; set; }
}

请注意我的orig csv中的Ping Pong标题

我尝试使用CsvHelper但没有成功,因为它正在使用流而不是字符串而我尝试转换解析失败

编辑对我来说无论是否使用CsvHelper都没关系,最后我想将csv转换为List<Model>

我该怎么做?

3 个答案:

答案 0 :(得分:10)

您可以使用StringReader变量创建csv

var textReader = new StringReader(csv);

var csvr = new CsvReader(textReader);
var records = csvr.GetRecords<Model>();

如果你想要自己的解析器:

var lines = csv.Split(new char[] {'\n'}, StringSplitOptions.RemoveEmptyEntries).Skip(1);
List<Model> models = new List<Model>();

foreach (var item in lines)
{
    var values = item.Split(',');
    var model = new Model
    {
        Foo1 = values[0],
        Foo2 = values[1],
        Foo3 = values[2],
        Foo4 = values[3],
        Foo5 = values[4],
        Foo6 = values[5],
        Ping_Pong = values[6],
    };

    models.Add(model);
}

修改

要使用CsvHelper解决标头问题,您需要创建一个映射配置类,指定标头和属性之间的映射:

public class ModelMap : CsvClassMap<Model>
{
    public ModelMap()
    {
        Map(m => m.Foo1);
        Map(m => m.Foo2);
        Map(m => m.Foo3);
        Map(m => m.Foo4);
        Map(m => m.Foo5);
        Map(m => m.Foo6);
        Map(m => m.Ping_Pong).Name("Ping Pong");
    }
}

像这样使用:

var textReader = new StringReader(csv);

var csvr = new CsvReader(textReader);
csvr.Configuration.RegisterClassMap<ModelMap>();

var records = csvr.GetRecords<Model>();

答案 1 :(得分:0)

问题是您的数据集(csv字符串)缺少一列(您指定了7列,但csv中缺少Ping Pong列)。默认行为是throw,但您可以设置config选项以忽略缺少的列:

此处的工作代码:

var config = new CsvConfiguration();
// setting this will cause the missing Ping Pong field to be ignored
config.WillThrowOnMissingField = false;

// we wrap your string in a StringReader to make it accessible to CsvReader
var reader = new CsvReader(new StringReader(csv), config);
var records = reader.GetRecords<Model>().ToList();
records.Dump();

答案 2 :(得分:-1)

要完全按照你的要求你可以使用它:

var modelStrings = csv.Split('\n').Skip(1);
var models = new List<Model>();
foreach(string s in modelStrings)
{
    var props = s.Split(',');
    models.Add(new Model(props[0],props[1],props[2],props[3],props[4],props[5],props[6]));

}
但请注意:这可能很慢,您可能需要添加更广泛的逻辑来实例化新模型以解决csv格式的可能变化。

编辑:

为了澄清它的作用,它首先将跳过第一个的新行拆分csv字符串。然后它使用该列表中的每个字符串并用逗号分隔它们以获取值列表(模型属性)以使用

实例化Model类