优先用 file.readlines 而非 readalllines 避免 oom;非 utf-8 编码需显式指定 encoding;count() 会遍历全部行;streamreader 更灵活可控;超大文件可考虑 span 扫描字节换行符。

用 File.ReadLines 避免内存爆炸
直接读整个文件再按换行符切分(比如 File.ReadAllText + Split('\n'))在大文件上会把全部内容加载进内存,几 GB 的日志一读就 OOM。而 File.ReadLines 返回的是 IEnumerable<string></string>,按需逐行迭代,内存占用几乎恒定。
实操建议:
- 永远优先用
File.ReadLines(path).Count(),不是File.ReadAllLines - 如果文件编码非 UTF-8(比如 GB2312),必须显式传入
Encoding参数,否则可能乱码或抛IOException - 注意:
Count()会遍历全部行,没有“跳过内容只数换行符”的捷径——行数本质就是行迭代器走完的次数
StreamReader 手动计数更可控
当需要跳过 BOM、处理不规范换行(\r\n / \n / \r 混用)、或中途提前退出时,StreamReader 更灵活。
示例关键逻辑:
int lineCount = 0;
using (var sr = new StreamReader(path, Encoding.UTF8))
{
while (sr.ReadLine() != null) lineCount++;
}
注意事项:
一个功能强大、性能卓越的企业建站系统。使用静态网页技术大大减轻了服务器负担、加快网页的显示速度、提高搜索引擎推广效果。本系统的特点自定义模块多样化、速度快、占用服务器资源小、扩展性强,能方便快捷地建立您的企业展示平台。简便高效的管理操作从用户使用的角度考虑,对功能的操作方便性进行了设计改造。使用户管理的工作量减小。网站互动数据可导出Word文档,邮件同步发送功能可将互动信息推送到指定邮箱,加快企业
-
ReadLine()自动处理各种换行符,返回值为null表示 EOF,比手动找\n字节安全得多 - 若文件末尾缺换行符,最后一行仍会计入——这符合绝大多数场景下的“行数”语义
- 想跳过空行?加个
if (!string.IsNullOrWhiteSpace(line)) lineCount++
超大文件(>10GB)考虑用 Span<byte></byte> 扫描换行符
纯计数且文件极大时,ReadLine() 的字符串分配开销会累积成瓶颈。此时可绕过字符解码,直接扫描原始字节里的换行符(0x0A 或 0x0D 0x0A)。
但要注意:
- 必须确认文件编码是单字节(如 ASCII、UTF-8),多字节编码(UTF-16/32)不能这么干
- Windows 换行符
\r\n是两个字节,得避免把孤立的\r或\n误判为行尾 - 实际性能提升取决于文件大小和磁盘 I/O,SSD 上对几十 MB 文件没必要上这种方案
别踩这些坑
常见翻车点:
- 用
File.ReadAllLines(path).Length—— 内存爆掉前你不会意识到它有多危险 - 忽略 BOM:UTF-8 带 BOM 的文件,
ReadLines默认能处理,但自己用StreamReader时没传Encoding.UTF8可能吞掉首行 - 把
Environment.NewLine当文件换行符用——它只是当前系统的默认换行,和文件实际使用的无关 - 在非托管环境(如某些嵌入式 .NET 运行时)中,
File.ReadLines可能不可用,得回退到StreamReader
行数统计看着简单,但文件编码、换行约定、内存约束三者一叠加,最容易在“以为没问题”的地方卡住。尤其线上日志分析脚本,务必用真实大文件压测一遍。









