C#使用CSV标头为不同的变量赋值

时间:2018-05-29 10:58:20

标签: c# csv

我正在读取一个CSV文件,我基本上试图使用标题来确定文件中值的序号位置,尽管最后一部分给了我一些麻烦。以下是我到目前为止:

private static IEnumerable<Cow> ReadCowStream(Stream source)
    {
        bool isHeader = true;
        var cows = new List<Cow>();

        using (var reader = new StreamReader(source))
        {
            while (!reader.EndOfStream)
            {
                var line = reader.ReadLine();
                if (line != null)
                {
                    var values = line.Split(',');

                    if (isHeader && values.Contains("Weight") && values.Contains("Age"))
                    {
                        isHeader = false;
                    }
                    else
                    {
                        cows.Add(new Cow(
                            weight: values[0],
                            age: values[1]));
                    }
                }
            }
        }

        return animals;
    }

示例CSV:

Weight,Age
300,10
319,11
100,1
370,9

在这种情况下,输出将是List<Cow>,第一个条目的值为“Weight”:“300”和“Age”:“10”显然,但是如果“Weight”和“Age”是逆转吗?然后我会将错误的值分配给错误的变量。

基本上,我想使用标题来确定是否将values[0]放入weightage等等,因为我认为我无法保证哪个首先出现在我在读CSV。

3 个答案:

答案 0 :(得分:5)

使用像CsvHelper这样的库,可以根据标题名称而不是索引来提取值。

private static IEnumerable<Cow> ReadCowStream(Stream source) {
    var cows = new List<Cow>();
    using (var reader = new StreamReader(source)) {
        var csv = new CsvReader(reader);
        csv.Read();
        csv.ReadHeader();
        while (csv.Read()) {
            cows.Add(new Cow(weight: csv["Weight"], age: csv["Age"]));
        }
    }
    return cows;
}

现在,正在读取的CSV中首先出现哪个标题并不重要。

该库允许强类型解析。

如果Cow是使用默认构造函数定义的,并且具有适当类型的属性

public class Cow {
    public int Age { get; set; }
    public int Weight { get; set; }
}

ReadCowStream可以简化为

private static IEnumerable<Cow> ReadCowStream(Stream source) {
    using (var reader = new StreamReader(source)) {
        var csv = new CsvReader(reader);
        return csv.GetRecords<Cow>().ToList();
    }
}

CSV阅读器将解析行,创建实例并通过将标题与属性名称匹配来分配值。

答案 1 :(得分:2)

您可以存储标题索引,例如:

cows.Add(new Cow(
    weight: values[weightIndex],
    age: values[ageIndex]));

然后按如下方式访问值:

{{1}}

答案 2 :(得分:0)

使用Cinchoo ETL - 一个开源库,您可以使用几行代码轻松解析csv

public class Cow
{
    public int Age { get; set; }
    public int Weight { get; set; }
}

static void Main(string[] args)
{
    string csv = @"Weight,Age
    300,10
    319,11
    100,1
    370,9";

    foreach (Cow rec in ChoCSVReader<Cow>.LoadText(csv).WithFirstLineHeader())
    {
        Console.WriteLine($"Age: {rec.Age}, Weight: {rec.Weight}");
    }
}