File.ReadAllLines 默认编码可能导致乱码,应显式指定Encoding;大文件宜用StreamReader.ReadLine逐行读取并using包裹;File.ReadLines有延迟执行和编码限制陷阱;中文乱码主因编码不匹配,ArgumentException多因路径含隐藏字符或非法符号。

用 File.ReadAllLines 读取全部行,但要注意编码问题
多数情况下,File.ReadAllLines 是最直接的选择——它返回 string[],每行一个元素。但它默认用 UTF-8(BOM 检测)或系统本地编码,如果文件是 GBK、UTF-16 或带 BOM 的 UTF-8,可能乱码或抛 IOException。
- 明确指定编码:比如
File.ReadAllLines("log.txt", Encoding.UTF8)或Encoding.GetEncoding("GBK") - 不确定编码时,先用
File.ReadAllBytes检查前几个字节是否含 BOM(0xEF 0xBB 0xBF→ UTF-8;0xFF 0xFE→ UTF-16 LE) - 大文件慎用:几 MB 就可能吃光内存,
ReadAllLines会一次性加载全部内容到数组
逐行读取用 StreamReader.ReadLine,适合大文件或流式处理
需要边读边处理、不希望全载入内存,或者文件超 10MB,就该用 StreamReader 配合 ReadLine。它按需读取,内存占用稳定。
- 务必用
using包裹:防止句柄泄漏,尤其在异常路径下 - 编码必须和文件一致:
new StreamReader("data.txt", Encoding.Default)中Encoding.Default是系统 ANSI,不是 UTF-8 -
ReadLine返回null表示 EOF,别当成空行;空行是返回空字符串"" - 注意换行符差异:Windows 是
,Linux 是,ReadLine自动剥离,不用手动TrimEnd(' ', ' ')
File.ReadLines 看似省事,但小心 LINQ 延迟执行陷阱
File.ReadLines 返回 IEnumerable,看起来既懒加载又简洁。但它只在枚举时打开文件——一旦你把它传给 .ToList()、.Count() 或多遍遍历,文件会反复打开,甚至抛 IOException(“文件正被另一进程使用”)。
- 单次遍历没问题:
foreach (var line in File.ReadLines("input.txt")) { ... } - 要多次访问?先
ToList()或ToArray()落地,但这就回到内存占用问题了 - 别对它做
Where(...).First()后再用原序列——文件已关闭,第二次枚举会失败 - 它不支持自定义编码,固定用 UTF-8(无 BOM)或检测 BOM,GBK 文件会直接乱码
遇到中文乱码或 ArgumentException: Illegal characters in path 怎么办
乱码本质是编码不匹配;ArgumentException 多半是路径里混了控制字符(比如从剪贴板粘贴时带了不可见的 u202a 或 uFEFF),或用了非法符号如 | ? *。
- 打印路径调试:
Console.WriteLine($"[{path.Replace(" ", "\0")}]"),看有没有隐藏字符 - 用
Path.GetFullPath(path)提前暴露相对路径解析问题 - 读取前先确认文件存在:
if (!File.Exists(path)) throw new FileNotFoundException(path);,避免后续错误掩盖根源 - 从用户输入获取路径时,用
Path.GetFileName和Path.GetDirectoryName拆解校验,比直接拼接更安全
实际写的时候,编码和路径这两块最容易卡住——不是语法错,而是运行时无声失败。多打一行日志,比查半天文档快。











