导出CSV中文乱码需加UTF-8 BOM(new UTF8Encoding(true)),字段含逗号、换行、双引号须按RFC 4180转义并加引号,大数据量用预估容量的StringBuilder,DateTime和数值需格式化,特殊字段前加单引号强制Excel识别为文本。

导出时中文乱码,是因为没设UTF-8 BOM
直接用 StreamWriter 写 CSV,不加 BOM 的话,Excel 打开中文基本全乱。Windows 记事本可能显示正常,但 Excel 默认按 ANSI 解码,根本不管你的 UTF-8。
实操建议:
- 用
new StreamWriter(path, false, new UTF8Encoding(true))—— 第三个参数true表示写入 BOM - 别用
Encoding.UTF8直接传,它默认BOM = false - 如果目标系统是 Linux 或 Python 脚本读取,反而要关 BOM(避免开头三个字节
EF BB BF干扰解析)
DataTable 列名含逗号、换行、双引号时会破坏 CSV 格式
CSV 不是“用逗号分隔的文本”那么简单。RFC 4180 规定:字段含 ,、" 或换行符时,必须用双引号包裹,且内部的双引号要变成两个双引号("")。
实操建议:
- 别手写拼接,用
string.Join+ 简单Replace很容易漏掉换行符或嵌套引号 - 推荐用
StringBuilder逐字段处理:value.Contains(",") || value.Contains("\"") || value.Contains("\n")为真时,先Replace("\"", "\"\""),再包上"..." - 空值统一转成空字符串
"",别留null,否则.ToString()可能抛NullReferenceException
大数据量下用 StringBuilder 比 string += 快十倍以上
一个 10 万行 × 50 列的 DataTable,如果每行都用 += 拼字符串,GC 压力大、内存暴涨、耗时飙升——不是卡在 IO,是卡在字符串反复拷贝。
实操建议:
- 初始化
StringBuilder时预估容量:new StringBuilder(estimatedSize),比如每行平均 200 字节 × 行数 - 列名行和数据行分开写,避免反复
AppendLine带来的冗余判断 - 导出前检查
DataTable.Rows.Count,0 行时直接写空列名,别跳过或报错
DateTime 和 numeric 类型导出后 Excel 显示为科学计数法或日期错乱
Excel 会自动识别字段内容:一串数字可能被转成科学计数法(如 123456789012345678 → 1.23E+17),日期字符串若格式不标准(如 "2023-01-01" vs "01/01/2023"),可能被识别成文本或错误日期。
实操建议:
-
DateTime字段统一用ToString("yyyy-MM-dd HH:mm:ss"),避免本地化格式(如 "2023年1月1日") - 数值类型调用
ToString(CultureInfo.InvariantCulture),防止小数点变成逗号 - 如果想让 Excel 强制当文本(比如身份证号、订单号),在值前加英文单引号:
'123456789012345678(注意:只对 Excel 有效,其他工具可能显示单引号)
最麻烦的其实是字段类型动态变化——DataTable 里一列可能是 int、null、string 混用。导出前最好先 Rows.Cast 过一遍,统一转成字符串并做格式化,别依赖 .ToString() 的默认行为。











