使用Java统计目录中文件的数量

28 浏览
0 Comments

使用Java统计目录中文件的数量

如何使用Java计算目录中文件的数量?为了简单起见,假设该目录没有子目录。我知道标准的方法是:

new File().listFiles().length

但是,这实际上会遍历目录中的所有文件,如果文件数量很多,则可能会花费很长时间。此外,除非目录中的文件数量大于某个固定的大数字(比如5000),否则我不关心目录中实际的文件。我猜测,但是目录(或Unix的i-node)是否存储其包含的文件数量?如果我能够直接从文件系统获取该数字,将会更快。每当Tomcat服务器上的后端开始进行真正的处理之前,我需要在每个HTTP请求上进行此检查。因此,速度非常重要。我可以定期运行一个守护程序来清除目录。我知道这一点,请不要给我这个解决方案。

admin 更改状态以发布 2023年5月21日
0
0 Comments

从Java 8开始,您可以用三行代码实现:

try (Stream files = Files.list(Paths.get("your/path/here"))) {
    long count = files.count();
}

关于5000个子节点和inode方面:

这种方法会遍历所有的条目,但正如Varkhan所建议的,您可能无法做得比这更好,除非使用JNI或直接执行系统命令调用,但即使那样,您也无法确定这些方法不会做同样的事情!

然而,让我们深入一下:

查看JDK8源代码,Files.list暴露了一个使用Files.newDirectoryStreamIterable的流,该流委托给FileSystemProvider.newDirectoryStream

在UNIX系统上(反编译sun.nio.fs.UnixFileSystemProvider.class),它加载了一个迭代器:使用sun.nio.fs.UnixSecureDirectoryStream(遍历目录时带有文件锁)。

因此,在这里有一个将通过条目循环的迭代器。

现在,让我们看一下计数机制。

实际计数是通过Java 8流公开的count/sum reducing API执行的。理论上,此API可以轻松执行并行操作(使用多线程)。然而,流是使用禁用并行性创建的,因此不可行……

这种方法的好处是,它不会将数组加载到内存中,因为条目将被迭代器计数,同时由底层(文件系统)API读取。

最后,提供一个信息,概念上,在文件系统中,目录节点不需要保存它包含的文件数量,它只能包含其子节点的列表(inode列表)。我不是关于文件系统的专家,但我相信UNIX文件系统就是这样工作的。因此,您无法假设直接获取此信息的方法(即:可能始终有一些隐藏的子节点列表)。

0
0 Comments

啊...Java中没有直接实现这个功能的理由是因为文件存储抽象化:有些文件系统可能无法立即提供目录中文件数量...这个计数甚至可能没有任何意义(例如,分布式,P2P 文件系统、将文件列表存储为链接列表的 fs,或者基于数据库的文件系统...)。

所以,使用

new File().list().length

可能是你最好的选择。

0