C#异步写入文件 C#如何用async await写文件

来源:这里教程网 时间:2026-02-21 17:43:22 作者:

File.WriteAllTextAsync
最简单,但要注意编码和路径合法性

直接替换同步的

File.WriteAllText
即可,它返回
Task
,支持
await
。默认使用 UTF-8(无 BOM),如果需要带 BOM 或其他编码(如 GB2312),必须显式传入
Encoding
参数,否则可能乱码:

await File.WriteAllTextAsync("log.txt", "内容", Encoding.UTF8);

常见错误是传入 null 路径或包含非法字符(如

*
?
)的文件名,会抛出 <code>ArgumentException
;目录不存在时不会自动创建,需提前调用
Directory.CreateDirectory

StreamWriter
配合
using
是流式写入的推荐方式

适合写入大文本、分段追加、或需要控制缓冲行为的场景。必须用

async
版本的
WriteAsync
WriteLineAsync
,否则会阻塞线程:

using var sw = new StreamWriter("data.json", append: true) { AutoFlush = true };
await sw.WriteLineAsync(JsonSerializer.Serialize(obj));

注意点:

AutoFlush = true
可避免 await 期间数据滞留在缓冲区未落盘
不要手动调用
sw.Flush()
—— 它是同步的,会抵消 async 效果
若需指定编码,构造时传入
new StreamWriter(path, append, encoding)

别用
FileStream.WriteAsync
直接写字符串,容易出编码问题

它只接受

byte[]
,必须自己编码转换。新手常犯的错是这样写:

// ❌ 错误:没指定编码,且 string → byte[] 转换不明确
var bytes = Encoding.Default.GetBytes(text);
await fs.WriteAsync(bytes, 0, bytes.Length);

正确做法是统一用

UTF8
并显式处理:

var utf8Bytes = Encoding.UTF8.GetBytes(text);
await fs.WriteAsync(utf8Bytes, 0, utf8Bytes.Length);

但除非你有特殊性能要求(比如复用缓冲区、零分配写入),否则优先走

StreamWriter
File.WriteAllTextAsync
,更安全。

并发写同一个文件?小心
IOException
和数据覆盖

File.WriteAllTextAsync
是“覆盖写”,多任务同时调用会导致后写入者完全覆盖前者的全部内容;
StreamWriter
开启
append: true
也只是在打开时定位到末尾,写入过程仍非原子操作。真实并发场景下:

lock
SemaphoreSlim
控制写入顺序
改用日志框架(如 Serilog)内置的异步文件 sink,它已处理队列与线程安全 或把每条记录写入独立临时文件,再由单个后台任务合并

异步不等于线程安全 —— 这是最容易被忽略的前提。

相关推荐

热文推荐