file静态类适用于基础场景,但大文件、编码异常或并发访问时需切换至filestream+streamreader/streamwriter组合;file.readalltext/writealltext默认utf-8易因编码不匹配乱码,应显式指定编码或使用.net 6+自动探测;streamreader.readline()在文件末尾无换行符时仍能读取最后一行;file.copy需设overwrite参数true,file.move前应检测文件是否被占用;filestream的filemode与fileaccess必须合理搭配,否则抛异常。

File 静态类足够应付大多数基础场景,但直接用它写大文件、处理编码异常或并发访问时容易出错——关键不在“会不会”,而在“在哪种情况下该换哪种方式”。
File.ReadAllText 和 File.WriteAllText 什么时候会乱码?
这两个方法默认用 UTF-8 编码读写,但如果源文件是 GBK、UTF-16 或带 BOM 的 UTF-8,File.ReadAllText 可能读出乱码或抛 ArgumentException。
- 显式指定编码:用
File.ReadAllText(path, Encoding.UTF8)或Encoding.GetEncoding("GBK") - 自动探测编码(.NET 6+):改用
File.ReadLines(path, Encoding.Default)不行,得自己用StreamReader配合StreamReader.CurrentEncoding判断 - 写入时加 BOM:用
new UTF8Encoding(true)构造编码器传给WriteAllText,否则某些编辑器(如记事本)可能误判为 ANSI
StreamReader.ReadLine() 为什么读不到最后一行?
当文件末尾没有换行符时,StreamReader.ReadLine() 会返回最后一行内容,但不会触发循环结束条件——它返回非 null 值,而下一次调用才返回 null。这不是 bug,是设计行为。
- 安全写法:用
while ((line = reader.ReadLine()) != null)是正确的,但要注意最后一行一定被读到了 - 更稳妥的替代:用
File.ReadAllLines(),它内部已处理末尾无换行的情况,返回完整数组 - 大文件慎用:如果文件超 100MB,
ReadAllLines会一次性加载全部行到内存,此时必须坚持流式读取
File.Copy 和 File.Move 报“文件正由另一进程使用”怎么办?
错误信息是 IOException: The process cannot access the file because it is being used by another process.,常见于日志文件、数据库文件或被其他 FileStream 打开后未释放的文件。
- 检查是否遗漏
using或忘记调用Close()/Dispose(),尤其在FileStream、StreamWriter实例上 -
File.Copy默认不覆盖,加第 3 个参数true:File.Copy(src, dst, true) - 移动前强制释放句柄:用
Process.GetProcesses()查找占用进程太重,推荐先尝试File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read)测试能否打开,再决定是否重试或提示用户关闭程序
FileStream 构造时 FileMode 和 FileAccess 怎么配?
配错会导致 UnauthorizedAccessException 或 NotSupportedException,比如用 FileMode.Create 却只声明 FileAccess.Read,就会报错。
-
FileMode.Create+FileAccess.Write:清空并写入新内容(最常用) -
FileMode.OpenOrCreate+FileAccess.ReadWrite:存在则打开,不存在则创建,可读可写 -
FileMode.Append必须搭配FileAccess.Write,且不能用于读取 - 若要同时读写又避免覆盖,用
FileMode.Open+FileAccess.ReadWrite+FileShare.Read
File.ReadAllText/File.WriteAllLines 就够了;但只要涉及编码不确定、文件大于 50MB、需要部分更新或跨进程共享,就得立刻切到 FileStream + StreamReader/StreamWriter 组合——不是为了炫技,是绕不开的约束。










