streamwriter必须显式关闭或用using释放,否则因缓冲机制内容可能不写入磁盘;编码需显式指定utf-8带bom以兼容windows记事本;追加写入应设append:true参数;一次性写入优先用file.writealltext。

StreamWriter 必须显式关闭或用 using 释放,否则内容可能不写入磁盘
这是最常踩的坑:调用 WriteLine() 后文件仍是空的,或者只写入部分内容。因为 StreamWriter 默认启用缓冲,数据先存内存,不主动刷新或关闭就不会落盘。
正确做法是始终用 using 语句包裹:
using (var writer = new StreamWriter("log.txt"))
{
writer.WriteLine("Hello");
writer.WriteLine("World");
} // ← 此处自动调用 Dispose(),触发 Flush() + 关闭流
- 手动调用
Close()或Dispose()也行,但容易遗漏异常路径 - 千万别只靠 GC 回收——它不保证何时运行,也不保证调用
Dispose() - 如果必须长期持有 writer(如日志服务),则每次写完要调用
Flush()
编码问题:不指定 Encoding 参数时默认 UTF-8 无 BOM,但旧系统可能读错
Windows 记事本打开某些 StreamWriter 写出的文件显示乱码,往往是因为编码不匹配。.NET 6+ 中 new StreamWriter(path) 默认用 Encoding.UTF8(无 BOM),而老版记事本默认按 ANSI(如 GBK)解析。
- 要兼容 Windows 记事本,显式传入
Encoding.UTF8并设encoderShouldEmitUTF8Identifier: true(即带 BOM) - 更稳妥的做法是统一用
Encoding.UTF8(无 BOM)并确保读取端也按 UTF-8 解析 - 若需 ANSI 兼容,可用
Encoding.Default,但跨机器行为不可控,不推荐
示例(写带 BOM 的 UTF-8):
using (var w = new StreamWriter("data.txt", false, new UTF8Encoding(true)))
{
w.WriteLine("中文");
}
追加写入要用 append: true 构造参数,别依赖 FileMode.Append
直接传 FileMode.Append 给 FileStream 再包一层 StreamWriter 是错的——StreamWriter 不识别 FileMode,它只认底层流的位置。正确方式是构造 StreamWriter 时设 append: true:
using (var w = new StreamWriter("log.txt", true)) // ← true 表示追加
{
w.WriteLine($"[{DateTime.Now}] Info");
}
-
true会让 writer 自动将流位置移到末尾,并跳过清空文件操作 - 如果传
false(默认),即使文件存在也会被截断重写 - 不要混用
File.Open(..., FileMode.Append)和StreamWriter—— 容易因流位置未置位导致覆盖或错位
写入性能:小量文本直接用 File.WriteAllText 更简单,不用手管 StreamWriter
如果你只是「一次性写入整个字符串」,完全没必要手动 new StreamWriter。.NET 提供了更高层封装:
File.WriteAllText("config.json", jsonContent); // 默认 UTF-8 无 BOM
File.WriteAllText("readme.txt", text, Encoding.UTF8); // 可指定编码
- 内部就是用
StreamWriter实现的,但帮你省去了 using、编码、异常处理等细节 - 适合配置文件生成、临时文本保存等场景
- 只有需要「分多次写」「控制缓冲大小」「写入过程中响应取消」时,才值得上
StreamWriter
真正复杂的地方在于流生命周期管理与编码一致性——这两点没对齐,再简单的写入都会出问题。










