我正在读取一个 CSV 文件,基本上是在尝试使用 header 来确定文件中值的顺序位置,尽管最后一部分给我带来了一些麻烦。以下是我目前所拥有的:
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]
进入weight
或 age
等等,因为我无法保证我正在阅读的 CSV 文件中哪个排在第一位。
最佳答案
使用类似 CsvHelper 的库,可以根据 header 名称而不是索引提取值。
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 文件中哪个 header 排在第一位并不重要。
库允许强类型解析。
如果 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 阅读器将解析行、创建实例并通过将 header 与属性名称匹配来分配值。
关于C# 使用 CSV header 为不同的变量赋值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50582681/