优先用 File.ReadAllText 读取整个文件为字符串,File.ReadAllLines 返回行数组适合按行处理;大文件须用 StreamReader 流式读取,编码需显式指定 UTF-8 避免乱码,路径应先检查存在性并注意权限与环境差异。

用 File.ReadAllText 还是 File.ReadAllLines?看你要什么数据结构
直接读整个文件内容为字符串,用 File.ReadAllText;需要按行处理、后续要遍历或修改某几行,用 File.ReadAllLines。前者返回单个 string,后者返回 string[],别混用——比如对 File.ReadAllText 结果调 .Split('\n') 会漏掉 \r\n 换行、丢失原始换行符语义。
-
File.ReadAllText自动处理 BOM(如 UTF-8 带签名),但若文件无 BOM 又是 UTF-8 编码,它默认用系统本地编码(Encoding.Default)解码,可能乱码 -
File.ReadAllLines不保留空行末尾的换行符,且每行字符串不含\r或\n—— 如果你依赖换行符做格式校验,得自己补 - 大文件(>10MB)别用这两个,会一次性加载进内存,改用
StreamReader流式读取
编码不匹配导致乱码?必须显式指定 Encoding
Windows 记事本保存的 UTF-8 文件常带 BOM,而 VS 新建的文本文件默认无 BOM。File.ReadAllText("a.txt") 在 .NET 5+ 默认用 UTF-8(含 BOM 检测),但 .NET Framework 4.8 及更早版本默认用 Encoding.Default(通常是 GB2312/GBK),一读中文就变“”。
- 保险写法:统一显式传
Encoding.UTF8,如File.ReadAllText("log.txt", Encoding.UTF8) - 若不确定源文件编码,别硬猜——先用工具(如 VS Code)查看实际编码,或用
File.ReadBytes检查前 3 字节是否为EF BB BF(UTF-8 BOM) -
Encoding.UTF8和Encoding.GetEncoding("UTF-8")行为一致,但后者可能抛ArgumentException,优先用前者
路径不存在或权限不足?FileNotFoundException 和 UnauthorizedAccessException 得分开捕获
直接调 File.ReadAllText 而不检查路径,出错时堆栈里只看到顶层异常,但实际原因可能是路径拼错、相对路径解析错、或部署后目录没读权限。别只写一个 catch (Exception)。
- 先用
File.Exists(path)判断文件是否存在,比靠异常更高效;注意:网络路径或符号链接可能导致Exists返回false即使文件真实可访问 - 权限问题多见于 Windows 服务、IIS 应用池身份(如
ApplicationPoolIdentity),此时需给目标目录添加读取权限,而非改代码 - 路径含中文或特殊字符(如
%、#)时,确保传入的是原始路径字符串,不要被 URL 解码或日志框架意外转义
想边读边处理?用 StreamReader 配合 using 确保释放
读超大日志、CSV 或逐行解析 XML 片段时,File.ReadAllLines 会把全部内容塞进内存,容易触发 OutOfMemoryException。这时必须用流式读取。
- 正确写法:
using (var reader = new StreamReader("data.txt", Encoding.UTF8)) { string line; while ((line = reader.ReadLine()) != null) { // 处理单行 } } -
reader.ReadLine()返回null表示到 EOF,不是空字符串;空行返回"" - 别忘了
using——不手动Dispose()或不加using,文件句柄会泄漏,尤其在循环中反复打开文件时 - 如果要跳过前 N 行或只读前 M 行,用
StreamReader更灵活;File.ReadLines(返回IEnumerable)也支持延迟加载,但内部仍用StreamReader,且不能复用同一个枚举器多次
文件编码、路径解析、内存模型这三块最容易在上线后出问题——尤其是跨环境(开发机 vs Docker 容器 vs Windows Server)时,连“文件存在”这个前提都可能因工作目录或挂载方式不同而失效。











