FileInfo.Length 最准,一行代码 new FileInfo(path).Length 即可获取文件真实字节数;它调用系统API直接读取元数据,不加载内容、无内存压力、支持符号链接和长路径,且比 File.GetAttributes 等错误方式可靠得多。

直接说结论:用 FileInfo.Length 最准,new FileInfo(path).Length 一行就能拿到字节数;别用 File.GetAttributes 或判断 Exists 后再查,那不是获取大小,是绕路。
为什么 FileInfo.Length 是首选
它底层调用的是 Windows API 的 GetFileSizeEx(或 Unix 的 stat),返回的是文件系统记录的真实字节长度,不读内容、不缓存、不触发权限检查(只要路径可访问)。而 File.ReadAllBytes().Length 会把整个文件加载进内存,几 GB 的文件直接 OOM;Stream.Length 在某些流(如网络流、压缩流)上根本不可用或抛 NotSupportedException。
-
FileInfo实例轻量,只做元数据查询,无副作用 - 支持符号链接(默认解析目标文件大小)
- 自动处理 UNC 路径、长路径(启用
longPathAware时)
File.GetAttributes 根本不返回大小
这是最常见的误解——File.GetAttributes(path) 返回的是 FileAttributes 枚举(比如 ReadOnly、Hidden),里面根本没有大小字段。有人误以为 FileAttributes 包含长度信息,其实是把属性和元数据搞混了。试图从返回值里“提取大小”,结果永远是 0 或编译报错。
- 错误写法:
var attr = File.GetAttributes(path); long size = (long)attr; // 完全没意义 - 正确替代:必须走
FileInfo或FileSystemInfo体系
注意 FileInfo 构造时的路径合法性
FileInfo 构造函数不会立即校验路径是否存在或是否为文件——它只是封装路径字符串。真正抛异常(如 DirectoryNotFoundException、UnauthorizedAccessException)是在你首次访问 .Length 时才发生。
- 如果路径是目录,访问
.Length会抛IOException:“The directory is not empty” 或 “Access to the path is denied”(取决于系统版本) - 若路径含非法字符(如
| ? *),构造FileInfo就会抛ArgumentException - 建议加一层判断:
if (File.Exists(path)) { var fi = new FileInfo(path); return fi.Length; },避免把目录当文件处理
大文件和权限场景下的实际表现
在 NTFS 上,FileInfo.Length 对几百 GB 的文件也几乎瞬时返回;但若文件被其他进程独占写入(如日志文件正在滚动),可能抛 IOException(“The process cannot access the file…”)。这不是大小获取逻辑的问题,而是系统级锁导致的元数据不可读。
- 不要用
try/catch来“探测”文件是否存在——先调File.Exists更高效 - 跨网络共享(SMB)时,
.Length延迟略高,但仍是唯一可靠方式;Directory.GetFiles返回的FileInfo数组里每个对象的.Length都需单独触发一次 RPC 调用 - Linux/macOS 下行为一致,但注意大小写敏感路径可能导致
FileNotFoundException
真正容易被忽略的是:FileInfo 不会自动刷新——如果文件在你创建实例后被外部修改,再次读 .Length 仍会返回缓存的旧值(.NET 6+ 已修复此问题,但旧版需重新 new 实例)。所以高频轮询时,别复用同一个 FileInfo 对象。










