推荐用 Directory.EnumerateFiles 配合 try/catch 逐个获取文件长度求和,避免内存暴涨和权限异常;FileInfo.Length 返回逻辑大小,非磁盘实际占用,硬链接、压缩、稀疏文件会导致统计偏差。

用 Directory.GetFiles 递归获取所有文件再求和最直接
想快速知道一个文件夹占了多少空间,核心就是把里面所有文件的 Length 加起来。别用 Directory.GetDirectories 套娃循环再查子目录——容易漏、难控制、还慢。直接让 Directory.GetFiles 一次性拉出全部路径更稳。
-
Directory.GetFiles(path, "*", SearchOption.AllDirectories)能拿到所有嵌套文件的完整路径,但遇到权限不足的子目录会直接抛UnauthorizedAccessException - 如果目录结构深或含大量小文件,一次性加载所有路径到内存可能吃掉几百 MB,尤其在低配机器上明显卡顿
- Windows 上某些系统文件(如
$Recycle.Bin或System Volume Information)默认不可读,必须捕获异常跳过,不能靠预判路径名规避
用 Directory.EnumerateFiles 更省内存且可控
真正生产环境推荐这个。它返回 IEnumerable<string></string>,边遍历边 yield,不缓存全量路径,内存占用几乎恒定,还能随时 break 或加条件过滤。
- 必须搭配
try/catch包住每次FileInfo.Length访问,因为单个文件也可能因被占用、权限变化或路径过长(>260 字符)而失败 - 注意
SearchOption.AllDirectories在符号链接(symlink)上行为:.NET 5+ 默认不跟随,旧版可能陷入死循环,需确认目标环境版本 - 避免用
new FileInfo(path).Length频繁构造对象,改用new FileInfo(path).Length前先检查File.Exists(path)—— 某些网络盘或 OneDrive 按需同步的文件,Exists返回 true 但Length仍可能抛IOException
统计结果不准?大概率是硬链接、稀疏文件或 NTFS 压缩干扰
Windows 下看到的“文件大小”和磁盘实际占用常不一致。.NET 的 FileInfo.Length 返回的是逻辑大小(字节数),不是物理占用。如果你要的是真实磁盘开销,得调用 Win32 API GetCompressedFileSize 或 GetDiskFreeSpaceEx,但绝大多数场景不需要这么深。
- NTFS 压缩文件:逻辑大小 100MB,实际只占 40MB,
Length仍返回 100MB - 硬链接指向同一份数据:两个路径都计入总和,导致重复计算
- 稀疏文件(如虚拟机镜像):中间大段空洞不占磁盘,但
Length算全长 - 若业务明确要求“磁盘已用空间”,建议改用
DriveInfo查剩余空间做反推,或接受Length是逻辑值的事实
简单可靠的一次性统计写法(含异常防护)
以下代码跑通率高,覆盖常见断点,不依赖外部库:
long totalSize = 0;
var files = Directory.EnumerateFiles(rootPath, "*.*", SearchOption.AllDirectories);
foreach (string file in files)
{
try
{
// 先跳过太长路径(避免 PathTooLongException)
if (file.Length > 260) continue;
totalSize += new FileInfo(file).Length;
}
catch (UnauthorizedAccessException) { /* 忽略无权访问目录下的文件 */ }
catch (FileNotFoundException) { /* 文件已被删除,跳过 */ }
catch (IOException) { /* 句柄被占用、脱机等,跳过 */ }
}
注意:"*.*" 不代表只匹配带点的文件,它等价于 "*";如果真要排除隐藏文件,得手动检查 File.GetAttributes(file) 是否含 FileAttributes.Hidden。
递归深度本身不是问题,但路径字符串拼接、异常频发、跨卷符号链接这三处最容易静默失败,动手前先拿一个已知结构的小目录验证逻辑是否走通。


















