用 File.ReadAllLines
最简单但不推荐大文件
如果文件很小(比如几百行以内),
File.ReadAllLines是最直觉的做法:它把全部内容加载进内存,返回字符串数组,直接取索引即可。
但要注意:行号从 0 开始,第 N 行对应索引
N - 1;若
N超出范围会抛
IndexOutOfRangeException。 示例:
string line = File.ReadAllLines("data.txt")[4]; 读第 5 行
必须加 try/catch或先检查
Length10MB 以上文件可能引发
OutOfMemoryException,尤其在低内存环境
用 StreamReader
逐行跳过更安全
这是真正“只读第 N 行”的标准做法——不加载全文,只按需读取前 N 行,内存占用恒定(约几 KB)。
核心逻辑是调用
ReadLine()N 次,丢弃前 N−1 行,保留第 N 次返回值。 注意:
StreamReader.ReadLine()返回
null表示已到文件末尾,需提前判断 别用
for (int i = 0; i 然后取最后一次结果——循环次数应为 <code>N,但读取动作要在循环内完成 示例片段:
string GetNthLine(string path, int n)
{
if (n < 1) throw new ArgumentException("行号从 1 开始");
using var sr = new StreamReader(path);
for (int i = 1; i < n; i++)
if (sr.ReadLine() == null) return null; // 提前结束
return sr.ReadLine();
}
用 File.ReadLines
看似简洁实则暗坑多
File.ReadLines返回
IEnumerable<string></string>,支持 LINQ 的
Skip/
Take,写起来像
File.ReadLines(p).Skip(n-1).FirstOrDefault(),但容易误用。 它不会立即读文件,而是延迟执行——看起来没开销,但每次枚举都重新打开文件(除非你缓存结果) 若反复调用该表达式,等于反复打开、逐行读到第 N 行,性能雪崩 不如直接用
StreamReader明确控制流,避免隐式行为 真要用 LINQ,至少包一层:
var lines = File.ReadLines(path).ToArray();——但这又回到内存全载的老路
Unicode、BOM 和换行符兼容性不能忽略
Windows 默认用
\r\n,Linux/macOS 用
\n,
StreamReader默认能识别;但若文件含 BOM(如 UTF-8 with BOM),
ReadLine不会吃掉它,首行内容开头可能带
\uFEFF。 打开时显式指定编码更稳妥:
new StreamReader(path, Encoding.UTF8)若需精确按字节偏移定位(极少数场景),得用
FileStream+ 自行解析换行符,但绝大多数情况没必要 行号定义本身依赖换行符——某行末尾缺
\n不影响计数,最后一行仍算一行
实际项目里,95% 的需求用
StreamReader循环跳过就足够稳;只有确认文件永远小且简单时,才考虑
ReadAllLines。别被 LINQ 表面简洁骗了,延迟执行的副作用在日志分析或配置热加载里特别容易暴露。
