解决C#中CsvHelper读取CSV列时的表头异常问题
要读取以下CSV文件,将Step、Magnetization、Energy三列分别存入独立列表:
Step,Magnetization,Energy 1,0.009375,12 2,0.009375,12 3,0.009375,12 4,0.009375,12 5,0.009375,12
编写的原C#代码如下:
class Program { static void Main(string[] args) { string csvFilePath = @"ising.csv"; CsvConfiguration myConfig = new CsvConfiguration(CultureInfo.CurrentCulture) { Delimiter = "," }; using (var reader = new StreamReader(csvFilePath)) using (var csv = new CsvReader(reader, myConfig)) { List<double> xAxisForSteps = new List<double>(); List<double> yAxisForMagnetization = new List<double>(); List<double> yAxisForEnergy = new List<double>(); while (csv.Read()) { int step = csv.GetField<int>("Step"); double magnetization = csv.GetField<double>("Magnetization"); int energy = csv.GetField<int>("Energy"); xAxisForSteps.Add(step); yAxisForMagnetization.Add(magnetization); yAxisForEnergy.Add(energy); } } } }
运行时抛出第一个异常:
An unhandled exception of type 'CsvHelper.ReaderException' occurred in CsvHelper.dll
Additional information: The header has not been read.
You must call ReadHeader() before any fields can be retrieved by name.IReader state:
ColumnCount: 0
CurrentIndex: -1
HeaderRecord:IParser state:
ByteCount: 0
CharCount: 27
Row: 1
RawRow: 1
Count: 3
RawRecord:Step,Magnetization,Energy
添加csv.ReadHeader()后,又抛出第二个异常:
An unhandled exception of type 'CsvHelper.ReaderException' occurred in CsvHelper.dll
Additional information: No header record was found.
IReader state:
ColumnCount: 0
CurrentIndex: -1
HeaderRecord:IParser state:
ByteCount: 0
CharCount: 0
Row: 0
RawRow: 0
Count: 0RawRecord:
问题原因与修复方案
第一个异常是因为通过列名读取字段前必须先读取表头,但直接添加ReadHeader()后出现第二个异常,是因为调用顺序错误:ReadHeader()需要在第一次调用csv.Read()读取表头行之后执行,同时要确保文件路径正确、文件存在且格式正常。
修正后的代码如下:
using System; using System.Collections.Generic; using System.Globalization; using System.IO; using CsvHelper; class Program { static void Main(string[] args) { string csvFilePath = @"ising.csv"; // 先确认文件存在,避免因路径错误或文件缺失导致无表头异常 if (!File.Exists(csvFilePath)) { Console.WriteLine($"文件不存在:{csvFilePath}"); return; } var myConfig = new CsvConfiguration(CultureInfo.CurrentCulture) { Delimiter = ",", // 若CSV表头存在大小写差异,可开启以下配置忽略验证 // HeaderValidated = null, // MissingFieldFound = null }; using (var reader = new StreamReader(csvFilePath)) using (var csv = new CsvReader(reader, myConfig)) { List<double> xAxisForSteps = new List<double>(); List<double> yAxisForMagnetization = new List<double>(); List<double> yAxisForEnergy = new List<double>(); // 关键:先读取表头行,再解析表头,最后循环读取数据行 csv.Read(); csv.ReadHeader(); while (csv.Read()) { int step = csv.GetField<int>("Step"); double magnetization = csv.GetField<double>("Magnetization"); int energy = csv.GetField<int>("Energy"); xAxisForSteps.Add(step); yAxisForMagnetization.Add(magnetization); yAxisForEnergy.Add(energy); } // 可选:验证读取结果 Console.WriteLine($"成功读取{xAxisForSteps.Count}行数据"); } } }
关键修正点
- 调用顺序:必须先调用
csv.Read()读取表头所在的行,再调用csv.ReadHeader()解析表头,之后才能循环读取数据行。 - 文件存在性检查:添加文件存在判断,排除因路径错误或文件缺失导致的异常。
- 配置优化:如果CSV表头存在大小写不一致的情况,可在配置中添加
HeaderValidated = null和MissingFieldFound = null来忽略相关验证错误(按需使用)。
内容的提问来源于stack exchange,提问作者user366312

