File.ReadAllLines 会爆内存,因它一次性将整个文件加载进内存,仅适合小配置文件。

用 File.ReadAllLines 读大文件会爆内存
它一次性把整个文件加载进内存,适合小配置文件(
- 只在确认文件大小可控时用,比如读
appsettings.json或临时生成的短列表 - 替代方案:改用
File.ReadLines—— 它返回IEnumerable<string></string>,真正按需拉取,内存占用几乎恒定 - 注意:
ReadLines不是“逐字符”,而是“逐行”,底层用StreamReader缓冲,行末识别依赖\n或\r\n
StreamReader.ReadLine() 是最稳的逐行控制方式
需要精细控制(比如跳过空行、解析失败就中断、带超时)时,必须手动管理流。这是底层最可靠的选择,也是 ReadLines 的内部实现基础。
- 务必用
using包裹,否则文件句柄泄漏,Windows 下可能报IOException: The process cannot access the file - 编码要显式指定,比如
new StreamReader("log.txt", Encoding.UTF8);不传默认 ANSI,在中文 Windows 上常乱码 -
ReadLine()返回null表示 EOF,别当成空字符串处理 —— 这是新手最常写的逻辑漏洞
带 BOM 的 UTF-8 文件会让 ReadLines 首行多出乱码
某些编辑器(如 VS Code 默认)保存 UTF-8 时加了 BOM(EF BB BF),ReadLines 不会自动剥离,首行开头会出现  这类符号。
- 检查方法:用十六进制工具看文件头,或在代码里打印
line[0]的(int)值是否为 65279 - 安全写法:用
new StreamReader(path, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)) - 或者统一用
File.ReadLines(path, Encoding.UTF8)—— .NET Core 3.0+ 已修复此问题,但 .NET Framework 4.x 仍存在
用 File.ReadLines 做 LINQ 查询要注意延迟执行
它返回的是“可枚举对象”,不是数组。写 var lines = File.ReadLines("x.log").Where(...).Take(10) 看似简单,但如果你之后又想遍历一遍,第二次调用会报 ObjectDisposedException —— 因为底层 StreamReader 已关闭。
- 需要多次遍历?立刻转成
ToList()或ToArray() - 只想取前 N 行且不重复读?
Take(N)没问题,它不会触发全量读取 - 配合
File.Copy或重命名操作时,确保ReadLines的迭代已完成,否则文件可能被锁定


















