StreamWriter不自动创建目录且默认覆盖文件;需手动创建目录、显式指定追加模式、用using确保刷新、按需选择编码。

StreamWriter 本身不自动创建目录,路径不存在时会直接抛出 DirectoryNotFoundException;它也不默认追加写入,新写入会覆盖原文件——这两点是绝大多数初学者踩坑的根源。
StreamWriter 构造时路径不存在就报错?先确保目录存在
常见错误现象:System.IO.DirectoryNotFoundException: Could not find a part of the path,哪怕你只写了 "logs/app.log" 这种看似合理的路径。
原因在于 StreamWriter 不负责创建中间目录,只检查最终路径的父目录是否存在。
实操建议:
- 写入前手动调用
Directory.CreateDirectory(Path.GetDirectoryName(filePath)),它会静默创建所有不存在的父级目录(比如"logs"不存在就一并建好) - 不要依赖
File.CreateText()来绕过——它底层仍是StreamWriter,同样会失败 - 如果路径来自用户输入或配置,务必用
Path.GetFullPath()规范化后再检查,避免相对路径歧义
StreamWriter 默认覆盖文件,想追加得显式传 true
使用场景:日志记录、批量导出、增量写入 CSV —— 这些都需要在原文件末尾添加内容,而不是每次重写。
关键参数差异:
-
new StreamWriter(filePath)→ 覆盖模式(append = false默认值) -
new StreamWriter(filePath, true)→ 追加模式(第二个参数必须是true,不是字符串"true") - 注意:即使文件为空,追加模式也会把光标定位到末尾,不会额外插入空行
示例:
using (var sw = new StreamWriter("data.txt", true))
{
sw.WriteLine($"[{DateTime.Now:HH:mm:ss}] Process started");
}
不显式调用 Close() 或用 using,文件可能写不全
现象:程序运行完,打开文件发现最后一两行缺失,或者文件大小始终为 0 字节。
原因:StreamWriter 内部有缓冲区,默认不立即刷盘;未 Dispose() 或 Close() 就退出作用域,缓冲数据就丢了。
实操建议:
- 必须用
using语句包裹,这是最稳妥的方式(Dispose()会自动Flush()+Close()) - 避免手动调用
sw.Close()后再写入——会抛ObjectDisposedException - 极少数需要延迟刷盘的场景(如高频日志),可设
sw.AutoFlush = true,但会轻微影响性能
编码乱码?别依赖默认 UTF-8 BOM,按需指定 Encoding
常见问题:用记事本打开写入的文件,中文显示为“口口口”;或 Excel 导入 CSV 时文字错位。
根本原因:StreamWriter 默认用 UTF-8 编码,但**不带 BOM**;而 Windows 记事本在无 BOM 时会误判为 ANSI(通常是 GB2312)。
解决方式:
- 明确传入
Encoding.UTF8(带 BOM 的版本需用new UTF8Encoding(true)) - 若目标系统是 Linux/跨平台工具,优先用无 BOM 的
Encoding.UTF8(更标准) - 导出给 Excel 用的 CSV,建议用
Encoding.Default(即系统 ANSI),兼容性反而更好
示例(带 BOM 的 UTF-8,适配记事本):
using (var sw = new StreamWriter("report.csv", false, new UTF8Encoding(true)))
{
sw.WriteLine("姓名,年龄");
}
真正容易被忽略的是:路径合法性检查和编码选择往往在调试后期才暴露,但它们的影响是静默且不可逆的——写错一次,数据就丢了,没有“重试”机会。










