读取 CSV 时中文变问号是因未指定 UTF- 8 编码,Windows 下 Encoding.Default 默认为 GBK,导致 UTF- 8 文件解码错位;应显式用 Encoding.UTF8 构造 StreamReader 或 StreamWriter(写入时设 BOM),TextFieldParser 也须传入 Encoding.UTF8 参数。

读取 CSV 时中文变问号,大概率是没指定编码
Windows 系统下用 Encoding.Default 读 CSV,表面能跑通,实际会把 UTF- 8 格式的文件当 GBK 解码,中文直接变 ???。这不是文件损坏,是解码错位——就像用粤语听普通话广播,字都认识但意思全错。
- 绝大多数现代 CSV(尤其从 Excel、Python pandas 或网页导出)默认是 UTF-8,不含 BOM
-
Encoding.Default在简体中文 Windows 上等于 GBK,和 UTF- 8 不兼容 - 别信“打开不乱码就说明编码对”,记事本自动探测 BOM 或启发式判断,
StreamReader不会
用 StreamReader 显式指定 Encoding.UTF8
这是最轻量、最可控的方式,绕过系统默认编码陷阱。关键不是“选对”,而是“强制指定”。
- 构造
StreamReader时必须传入Encoding.UTF8,不能依赖无参构造函数 - 如果 CSV 带 BOM(开头三个字节
EF BB BF),Encoding.UTF8能自动识别;不带 BOM 也照常解码 - 避免用
File.ReadAllLines(path)—— 它内部用的就是Encoding.Default,无声崩坏
using (var reader = new StreamReader(path, Encoding.UTF8)) {string line; while ((line = reader.ReadLine()) != null) {// 按逗号分割、处理字段……} }
写入 CSV 时加 BOM 防 Excel 双击乱码
Excel 双击打开 UTF-8 CSV 时,经常显示乱码,不是它错了,是它没看到 BOM,误判成 ANSI。解决方案不是换编码,是补 BOM。
- 用
new StreamWriter(path, false, new UTF8Encoding(true))—— 第三个参数true表示写入 BOM - 别用
Encoding.UTF8直接传入(它默认 BOM 为 false),否则 Excel 依然懵 - 如果目标是跨平台工具(如 VS Code、LibreOffice),BOM 非必需;但只要涉及 Excel 双击打开,BOM 就是刚需
用 TextFieldParser 时编码必须显式传参
Microsoft.VisualBasic.FileIO.TextFieldParser 好用但藏坑:它的构造函数看似支持编码,但重载不明确,容易掉进默认编码陷阱。
- 必须用带
Encoding参数的构造函数:new TextFieldParser(stream, Encoding.UTF8) - 千万别用
new TextFieldParser(path)—— 它走的是Encoding.Default - 注意它不接受
string路径直接传入编码,得先用File.OpenRead+StreamReader包一层再传流
真正麻烦的不是“怎么设编码”,而是 CSV 本身没标准:有 BOM 没 BOM、字段含换行符、引号转义规则不一……编码只是第一道门。一旦开始处理真实业务里的 CSV(比如用户上传、财务系统导出),很快会撞上分隔符冲突或空行解析异常——那时再回头调编码,已经晚了。