发布于2026-07-09 阅读(0)
扫一扫,手机访问
说到Ja va里遍历文件系统、统计文件夹大小,很多人第一反应是递归调用`listFiles()`,甚至有人直接跑外部命令。但在生产环境下,真正稳妥的做法还得靠`Files.walkFileTree()`配合自定义的`FileVisitor`——它不会一股脑把所有路径加载到内存里,也不依赖平台命令,更重要的是,它能稳稳地处理符号链接、权限异常这些边界情况。

具体怎么操作?其实你真正需要关心的,只有`visitFile`方法——每次遍历到普通文件时,把它的字节大小累加起来就行了。其他方法嘛,按需补充就行:
visitFile():调用 Files.size(path) 获取文件大小,加到一个共享的累加器里,比如 AtomicLongvisitFileFailed():这是用来兜底的——遇到无权限、文件被占用等情况时,捕获异常然后跳过,避免整个遍历中断preVisitDirectory():如果你想过滤某些目录(比如跳过 .git),或者检测循环软链,就在这儿做文章直接用 Files.size() 确实可能抛出 IOException,比如访问 /proc 下的伪文件时。所以 visitFileFailed 是必不可少的兜底逻辑。另外,别在 visitFile 里用 toFile().length() 来绕开异常——那不仅慢,遇到路径里带特殊字符的文件还可能直接翻车。
walkFileTree 会直接抛出 NotDirectoryExceptionwalkFileTree 就有点大材小用了,改用 Files.list() + 手动递归更合适AtomicLong 就行了,比 synchronized 块轻量得多下面这段代码可以拿来直接用:它统计目标目录的总字节数,自动跳过那些读不了的条目,而且支持软链跟随控制。
long total = new AtomicLong(0).get();
Files.walkFileTree(startPath, EnumSet.of(FOLLOW_LINKS), Integer.MAX_VALUE,
new SimpleFileVisitor() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
try {
total.addAndGet(Files.size(file));
} catch (IOException ignored) {}
return CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
return CONTINUE; // 忽略权限错误,继续遍历
}
});
System.out.println("Total: " + total + " bytes");
如果还想知道“遍历到第几层了”,或者按文件类型做个分类统计,那就在 preVisitDirectory 里维护个深度计数器,在 visitFile 里解析后缀名、分桶汇总。注意深度值是由 walkFileTree 的 maxDepth 参数和访问器内部状态共同决定的,没必要手动解析路径字符串。
ConcurrentHashMap 来存,key 通过 getFileExtension(file) 获取walkFileTree 的 maxDepth 参数,比在代码里判深度更高效volatile 标志位,返回 TERMINATE 就行
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8