C# CSV文件读取方法 C#如何读取和解析CSV文件

来源:这里教程网 时间:2026-02-21 17:42:34 作者:

TextFieldParser
读取 CSV 是最稳妥的内置方案

Windows Forms 或 .NET Framework 项目中,

Microsoft.VisualBasic.FileIO.TextFieldParser
是唯一能正确处理带引号、换行符、转义逗号等复杂 CSV 场景的原生类。它不依赖第三方包,且对编码(如 UTF-8 BOM)、字段截断、空行有明确行为。

常见错误是直接用

string.Split(',')
—— 遇到
"Smith, John",42,"123 Main St\nApt 4"
这类数据会彻底解析错。

必须指定
TextFieldType = FieldType.Delimited
并调用
SetDelimiters(",")
务必启用
HasFieldsEnclosedInQuotes = true
,否则引号内逗号无法识别为分隔符的一部分
ReadFields()
获取字符串数组,不要用
ReadLine()
后再手动切分
注意:该类位于
Microsoft.VisualBasic.dll
,需添加引用(即使项目是 C#)
using Microsoft.VisualBasic.FileIO;
// ...
using (var parser = new TextFieldParser("data.csv"))
{
    parser.TextFieldType = FieldType.Delimited;
    parser.SetDelimiters(",");
    parser.HasFieldsEnclosedInQuotes = true;
    parser.TrimWhiteSpace = true;
<pre class='brush:php;toolbar:false;'>while (!parser.EndOfData)
{
    string[] fields = parser.ReadFields(); // 自动处理引号、换行、转义
    Console.WriteLine(string.Join("|", fields));
}

}

在 .NET Core / .NET 5+ 中优先选
System.Text.Json
+ 自定义 CSV 解析器

.NET Core 起不再默认包含

TextFieldParser
(虽可通过 NuGet 引入
Microsoft.VisualBasic.Core
),但更推荐轻量可控的自定义逻辑——尤其当 CSV 结构固定、无嵌套换行时。

关键点不是“能不能读”,而是“怎么避免分配爆炸”和“如何应对空值/类型转换”。比如逐行

Split
后对每个字段调用
int.TryParse
比全加载进
List<string></string>
再批量转换更省内存。

StreamReader
逐行读取,避免一次性
File.ReadAllLines
占满内存
字段去引号逻辑必须手动实现:
field.StartsWith("\"") && field.EndsWith("\"") ? field.Substring(1, field.Length-2) : field
若需强类型映射(如转成
Person
对象),建议配合
Span<char></char>
做零分配解析,而非正则或 LINQ
警惕 BOM:UTF-8 文件开头可能有
\xEF\xBB\xBF
StreamReader
默认能识别,但自行
FileStream.Read
时要跳过

Microsoft.Data.Analysis.DataFrame
适合分析型场景,但别用于通用解析

如果你的目标是做数据清洗、统计或对接 ML.NET,

Microsoft.Data.Analysis
提供了类似 pandas 的
DataFrame
和内置 CSV 加载器。但它会把整张表加载进内存,且列类型推断不可控(比如把全数字 ID 列误判为
int
,遇到空值就崩)。

典型报错:

System.InvalidOperationException: Unable to convert column 'id' to type Int32 because of invalid value '' at row 123

仅在明确需要后续调用
df.Filter
df.GroupBy
等操作时才引入
必须传入
new DataFrameLoadOptions { HasHeader = true, InferTypes = false }
关闭自动类型推断
列名含空格或特殊字符时,
df["User Name"]
可用,但
df.User Name
会编译失败
不支持流式读取,无法处理 GB 级 CSV

第三方库
CsvHelper
的坑比功能还多

CsvHelper
功能强大,但默认行为极易引发静默错误:比如忽略首行标题却不报错、字段数不匹配时悄悄丢弃末尾列、空字符串转
DateTime
直接抛异常而非返回
null

真实项目里,90% 的 “CsvHelper 读不出来” 问题都源于没配

CsvConfiguration

必须显式设置
Configuration.Delimiter = ","
Configuration.Quote = '"'
,不能依赖默认
映射类属性名与 CSV 列名不一致?得用
[Name("user_id")]
Map(m => m.UserId).Name("user_id")
空值处理:对可空类型(
int?
,
DateTime?
)它能自动跳过,但对
string
字段,空字符串不会被转成
null
,得靠
ConvertUsing
手动干预
性能敏感场景慎用:反射绑定 + 大量字符串分配,比手写
Span<char></char>
解析慢 3–5 倍

真正难的从来不是“怎么读”,而是“怎么确保第 100001 行的引号没漏掉、空值没崩、编码没乱、内存没爆”。选方案前,先看你的 CSV 里有没有

"O'Reilly, Inc.", "C# \"Best Practices\"", 2024-04-01
这种数据 —— 有,就老实用
TextFieldParser
;没有,手写几行
StreamReader
+
Span
更省心。

相关推荐