<p>TextFieldParser 是 C# 解析 CSV 最稳妥方案,需显式指定 UTF-8 编码、调用 SetDelimiters(",") 和设置 HasFieldsEnclosedInQuotes = true;大文件应改用 StreamReader + 状态机流式解析;避免 LINQ to CSV,推荐 CsvHelper(配 HeaderValidated 校验)或 DataTable;务必处理 BOM 与编码问题。</p>

用 TextFieldParser 读 CSV 最稳,但别直接 new
它藏在 Microsoft.VisualBasic 命名空间里,C# 项目能用,而且专为 CSV/TSV 设计,自动处理带引号、换行、转义字段——比手撕 Split(',') 或硬套 StreamReader.ReadLine() 少踩 80% 的坑。
常见错误是直接 new TextFieldParser("file.csv"),结果中文路径乱码、BOM 头读错、空行崩掉。必须显式指定编码和配置:
-
TextFieldParser默认用Encoding.Default(通常是 GBK),UTF-8 文件得传Encoding.UTF8 - 务必调用
SetDelimiters(","),否则制表符也当分隔符 -
HasFieldsEnclosedInQuotes = true打开才能正确解析"John ""Doe"" Smith"这种嵌套引号
using (var parser = new TextFieldParser("data.csv", Encoding.UTF8))
{
parser.SetDelimiters(",");
parser.HasFieldsEnclosedInQuotes = true;
while (!parser.EndOfData)
{
string[] fields = parser.ReadFields(); // 这才是安全的逐行取数组
}
}大文件别加载进内存:用 StreamReader + 手写解析器
几 GB 的 CSV,TextFieldParser 会变慢(内部缓存+异常捕获开销大),DataTable.Load() 更是直接 OOM。这时候得自己流式拆行、按需解析字段。
关键不是“快”,而是“可控”:你能决定什么时候跳过某行、怎么转换数字、遇到脏数据是报错还是打日志。
- 用
StreamReader.ReadLine()逐行读,别File.ReadAllLines() - 字段分割不用
String.Split()—— 它无法识别引号包裹的逗号,改用状态机或正则(推荐Microsoft.Data.SqlClient里的轻量 CSV tokenizer,或用System.Text.Json的JsonDocument.ParseValue(ref)配合自定义 reader) - 数值字段用
double.TryParse()而非Convert.ToDouble(),避免脏数据炸掉整个批次
想用 LINQ 查数据?先选对库:别碰 LINQ to CSV
那个老库 LINQ to CSV 已多年不维护,不支持 .NET 6+,泛型映射常崩在空字段或类型推导上,错误信息是 NullReferenceException,根本看不出哪行哪列出问题。
替代方案就两个:
- 小数据 + 强类型:用
System.Data.DataTable+SqlBulkCopy(如果最终要进 SQL Server) - 中小数据 + 灵活映射:用
Newtonsoft.Json的JsonConvert.DeserializeObject<List<T>>()配合CsvHelper(注意:用CsvReader构造时传new CsvConfiguration(CultureInfo.InvariantCulture),否则数字小数点在某些区域设置下会解析失败)
示例中容易漏掉的是 CsvHelper 的 HeaderValidated 事件——它能让你在第一行读完后立刻校验列名是否匹配预期,而不是等到第 10 万行才报 Missing field 'Email'。
Encoding 和 BOM 是静默杀手,每次打开文件前都得看一眼
Windows 记事本存的 CSV 默认加 UTF-8 BOM(EF BB BF),而 TextFieldParser 和多数流读取器会把 BOM 当作首字段内容,导致第一列值开头多出乱码;Notepad++ 保存时选 “UTF-8 无 BOM” 才安全。
更隐蔽的是 ANSI 编码文件(其实是系统本地编码,比如中文 Win 是 GB2312)被当成 UTF-8 读——中文全变问号,但程序不报错,只是数据错得离谱。
- 用
File.ReadAllBytes()检查前 3 字节是不是0xEF, 0xBB, 0xBF来确认有无 BOM - 不确定编码时,先试
Encoding.UTF8,失败再 fallback 到Encoding.Default(但要知道这有平台依赖) - 生产环境建议统一要求上游提供 UTF-8 无 BOM 文件,并在代码里加断言:
if (bytes[0] == 0xEF) throw new InvalidOperationException("BOM not allowed");
CSV 解析真正的复杂点不在语法,而在编码、区域格式、空值表示(NULL / "" / <empty>)、以及字段内真实换行符——这些细节不提前约定,后面补救成本远高于一开始加三行校验逻辑。










