当我使用 Java 列出具有 300,000 个文件的目录的文件时,会发生内存不足。
String[] fileNames = file.list();
我想要的是一种可以增量列出目录的所有文件的方法,无论该特定目录中有多少文件,并且默认的 64M 堆限制不会出现“内存不足”问题。
我有一段时间谷歌了,在纯 Java 中找不到这样的方法。
请帮我!!
注意,JNI 是一种可能的解决方案,但我讨厌 JNI。
当我使用 Java 列出具有 300,000 个文件的目录的文件时,会发生内存不足。
String[] fileNames = file.list();
我想要的是一种可以增量列出目录的所有文件的方法,无论该特定目录中有多少文件,并且默认的 64M 堆限制不会出现“内存不足”问题。
我有一段时间谷歌了,在纯 Java 中找不到这样的方法。
请帮我!!
注意,JNI 是一种可能的解决方案,但我讨厌 JNI。
我知道您说“使用默认的 64M 堆限制”,但让我们看看事实 - 您希望使用 Java 提供给您的机制在内存中保存(可能)大量项目。所以,除非有一些你不能的可怕原因,否则我会说增加堆是要走的路。
这是 JavaRanch 上相同讨论的链接:http: //www.coderanch.com/t/381939/Java-General/java/iterate-over-files-directory
编辑,回应评论:我说他想在内存中保存大量项目的原因是因为这是 Java 提供的唯一机制,用于在不使用本机接口或平台特定机制的情况下列出目录(并且 OP 说他想要“纯Java”)。
对您来说唯一可能的解决方案是 Java7,然后您应该使用迭代器。
final Path p = FileSystems.getDefault().getPath("Yourpath");
Files.walk(p).forEach(filePath -> {
if (Files.isRegularFile(filePath)) {
//Do something with filePath
}
});
你在这里有点不走运。至少需要创建 300k 个字符串。平均长度为 8-10 个字符,每个字符 2 个字节,最小为 6Mb。为每个字符串(8 个字节)添加对象指针开销,就会遇到内存限制。
如果您绝对必须在一个目录中拥有这么多文件,我不建议这样做,因为您的文件系统会出现问题,那么最好的办法是通过 Runtime.exec 运行本机进程(而不是 JNI)。请记住,您会将自己束缚在操作系统上(ls vs dir)。您将能够以一个大字符串的形式获取文件列表,并负责将其后处理为您想要的内容。
希望这可以帮助。
在目录中拥有 300 000 个文件并不是一个好主意 - AFAIK 文件系统不擅长在单个节点中拥有那么多子节点。不过,有趣的问题。
编辑:以下没有帮助,请参阅评论。
我认为您可以使用 FileFilter,拒绝所有文件,然后在过滤器中处理它们。
new File("c:/").listFiles( new FileFilter() {
@Override public boolean accept(File pathname) {
processFile();
return false;
}
});