使用 Java 计算目录中的文件数

2022-08-31 13:34:56

如何使用Java计算目录中的文件数?为简单起见,让我们假设该目录没有任何子目录。

我知道的标准方法:

new File(<directory path>).listFiles().length

但是这将有效地遍历目录中的所有文件,如果文件数量很大,则可能需要很长时间。另外,我不关心目录中的实际文件,除非它们的数量大于某个固定的大数字(比如5000)。

我正在猜测,但是目录(或者在Unix的情况下是它的i-node)不是存储其中包含的文件数量吗?如果我能直接从文件系统中获取该数字,那将会快得多。在后端开始执行实际处理之前,我需要对Tomcat服务器上的每个HTTP请求进行此检查。因此,速度至关重要。

我可以每隔一段时间运行一个守护程序来清除目录。我知道这一点,所以请不要给我那个解决方案。


答案 1

啊。。。在Java中没有一个简单的方法是文件存储抽象:一些文件系统可能没有目录中随时可用的文件数量......该计数甚至可能根本没有任何意义(例如,请参阅分布式,P2P文件系统,将文件列表存储为链表的fs或数据库支持的文件系统...)。所以,是的,

new File(<directory path>).list().length

可能是你最好的选择。


答案 2

从Java 8开始,你可以用三行来做到这一点:

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

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

此方法将迭代条目,但正如Varkhan所建议的那样,除了玩JNI或直接系统命令调用之外,您可能无法做得更好,但即使这样,您也永远无法确定这些方法不会做同样的事情!

但是,让我们稍微深入研究一下:

查看 JDK8 源,公开一个流,该使用 from 将 委托给 。Files.listIterableFiles.newDirectoryStreamFileSystemProvider.newDirectoryStream

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

因此,有一个迭代器将遍历此处的条目。

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

实际计数由 Java 8 流公开的计数/总和减少 API 执行。从理论上讲,此 API 可以毫不费力地执行并行操作(使用多线程)。但是,流是在禁用并行性的情况下创建的,因此这是不行的...

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

最后,对于信息,从概念上讲,在文件系统中,目录节点不需要保存它所包含的文件的数量,它可以包含它的子节点列表(inode列表)。我不是文件系统方面的专家,但我相信UNIX文件系统就是这样工作的。因此,您不能假设有一种方法可以直接获得此信息(即:总会有一些子节点列表隐藏在某个地方)。


推荐