在 CsvHelper 中获取记录的长度

Getting length of records in CsvHelper

我正在使用 C# 中的 CsvHelper 库来读取 CSV 文件,如下所示:

var dataCsvFileReader = File.OpenText(inputFile);
var dataCsvReader = new CsvReader(dataCsvFileReader);
var dataRecords = dataCsvReader.GetRecords<dynamic>();

foreach(dynamic record in dataRecords){
    for(int i = 0; i < ???; i++){ //How many columns are there in the record???
        Console.WriteLine($"Record {i} value is: {record[i]}");
    }
}

从代码中可以看出,我的问题是我不知道记录中有多少列。由于在解析数据之前我不知道数据的结构(我作为输入的 CSV 文件总是不同的),我怎样才能找出有多少列?我试图查询 dataCsvReader.Context.ColumnCount 但总是 returns 0.

您应该记住做的一件事是在访问之前阅读 csv:

var dataCsvFileReader = File.OpenText(inputFile);
var dataCsvReader = new CsvReader(dataCsvFileReader);
dataCsvReader.Read();
var dataRecords = dataCsvReader.GetRecords<dynamic>();

我建议在此处使用 using 子句:

var dataCsvFileReader = File.OpenText(inputFile);
using(CsvReader dataCsvReader = new CsvReader(dataCsvFileReader))
{
    //read before accessing csv file
    dataCsvReader.Read();
    //count for columns
    var count = dataCsvReader.Context.ColumnCount;
    var dataRecords = dataCsvReader.GetRecords<dynamic>();
}

您可以将每条记录转换为List

using (TextReader dataCsvFileReader = File.OpenText(inputFile))
{
    using (CsvReader dataCsvReader = new CsvReader(dataCsvFileReader))
    {
        while (dataCsvReader.Read())
        {
            var dataRecord = Enumerable.ToList(dataCsvReader.GetRecord<dynamic>());
        }
    }
}

此处列出、计算和显示动态 CSV 值的解决方案。
为了阅读和查找列,您需要一些信息:分隔符、编码,如果文件有 header。没有这些,就无法实现这一目标。 在下面的示例中,我使用 header 和编码的默认值。

这里的想法是将 csv 转换为 List<Dictionary<string, object>>using 无法尽快释放 StreamReader

List<IDictionary<string, object>> dataRecords  ;

using (TextReader reader = new StreamReader(path))
using (var csvReader = new CsvReader(reader))
{
    csvReader.Configuration.Delimiter = ";";
    dataRecords = csvReader.GetRecords<dynamic>()
                           .Select(x =>  (IDictionary<string, object>)x) 
                           .ToList();
}

foreach (var record in dataRecords)
{
    // Print number of columns, and columns collection.
    Console.WriteLine($"-> {record.Count} Columns {{{string.Join(", ", record.Keys)}}}");
    foreach (var property in record.Keys)
    {
        Console.WriteLine(String.Format("\t{0} : {1}", property, record[property]));
    }
}

为了避免可能出现的性能瓶颈装箱,您可以使用像这样的字典:

.Select(x => new Dictionary<string, object>((IDictionary<string, object>)x))

结果:

-> 43 Columns {Method, Job, AnalyzeLaunchVariance,...}  
    Method : DiffOriginalNoAny  
    Job : Default  
    AnalyzeLaunchVariance : False  

-> 43 Columns {Method, Job, AnalyzeLaunchVariance,...}  
   Method : DiffOriginal  
   Job : Default  
   AnalyzeLaunchVariance : False  

你可以这样做:

        using (var reader = new StreamReader(file))
        using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
        {
            while (await csv.ReadAsync())
            {
                var count = csv.Context.Record.Length; // get the length of the record
            }
        }