最稳妥方案是用 StringBuilder 统一格式化每行(字符串加引号并转义、日期显式格式化、字段内换行预处理),再以 UTF-8 无 BOM 一次性写入;避免 WriteAllLines 和默认编码,分隔符优先选 或逗号。

用 StringBuilder 拼接对象属性再写入文件最稳妥
直接用 File.WriteAllLines 或 StreamWriter 逐行写,容易在中文、特殊字符、换行符上出问题。推荐先用 StringBuilder 统一格式化每行内容,最后一次性写入——既避免编码错乱,也减少 I/O 次数。
- 每行用制表符
或逗号分隔属性,比空格更可靠(空格可能出现在字段值里) - 字符串属性必须用双引号包裹,且内部双引号要转义为
""(CSV 规范),否则 Excel 打开会错列 - 日期、数字等非字符串类型建议显式调用
.ToString("yyyy-MM-dd HH:mm:ss"),别依赖默认格式 - 示例:
var sb = new StringBuilder(); foreach (var item in list) { sb.AppendLine($""{item.Name.Replace(""", """")} {item.Age} {item.CreatedAt:yyyy-MM-dd}"); } File.WriteAllText("data.txt", sb.ToString(), Encoding.UTF8);
导出含换行符的字段时,Environment.NewLine 不能直接塞进文本行
如果某个属性(比如 Description)本身含
或
,直接拼进一行会导致实际行数变多、结构错乱。Txt 不是结构化格式,没有“单元格内换行”的概念,必须预处理。
- 简单方案:把字段内的换行全替换成空格或
\n字面量,例如item.Description.Replace(" ", " ").Replace(" ", " ") - 严谨方案:按 CSV 规则包裹字段并转义,即仅当字段含
"、、或分隔符时才加引号,并对引号双写 - 别依赖
string.Join直接拼对象数组——它不会处理字段内换行,也不做转义
Encoding.UTF8 和 Encoding.Default 写出的 Txt 在 Windows 上表现不同
用 Encoding.Default(通常是 GBK)写中文,在记事本里可能显示正常,但用 VS Code、Excel 或跨平台读取时大概率乱码;而 Encoding.UTF8 是通用解,但 Windows 记事本默认不识别无 BOM 的 UTF-8。
- 解决记事本乱码:用
new UTF8Encoding(true)(带 BOM),但注意 BOM 会影响程序解析,如 Python 的pandas.read_csv可能报错 - 更兼容的做法:坚持用
Encoding.UTF8(无 BOM),并在文档里注明“请用支持 UTF-8 的编辑器打开” - 别省略编码参数——
File.WriteAllText(path, content)默认用 UTF-8 无 BOM,看似省事,但团队协作时容易踩坑
用 File.WriteAllLines 时,每行必须是完整字符串,不能包含
这个方法会自动在每个字符串末尾加 Environment.NewLine。如果你传进去的字符串自己带了
,结果就是空行+错位,尤其在日志类导出中特别隐蔽。
- 错误写法:
lines.Add($"{name} {age}"); File.WriteAllLines(..., lines)→ 实际写入两行 - 正确做法:确保每个
string元素是一行的全部内容,不含任何控制符 - 如果已有含
的字符串数组,先用string.Replace(" ", " ").Replace(" ", "")清洗 - 性能提示:
WriteAllLines底层仍是逐行写,大数据量时不如StringBuilder + WriteAllText一次刷盘
字段是否含不可见字符、导出后由谁打开、后续会不会被其他程序读取——这三个点没确认清楚前,别急着选分隔符或编码。Txt 看似简单,坏就坏在“看起来能打开就行”。










