Java 列出目录中的文件时的OutOfMemory

Java 列出目录中的文件时的OutOfMemory,java,file,out-of-memory,Java,File,Out Of Memory,当我用Java列出包含300000个文件的目录中的文件时,就会出现内存不足的情况 String[] fileNames = file.list(); 我想要的是一种方法,它可以增量列出一个目录中的所有文件,而不管该特定目录中有多少文件,并且不会出现默认64M堆限制的“内存不足”问题 我有一段时间使用谷歌,但在纯Java中找不到这样的方法。 请帮帮我 请注意,JNI是一种可能的解决方案,但我讨厌JNI。我知道您说过“使用默认的64M堆限制”,但让我们看看事实——您希望使用Java提供的机制在内存

当我用Java列出包含300000个文件的目录中的文件时,就会出现内存不足的情况

String[] fileNames = file.list();
我想要的是一种方法,它可以增量列出一个目录中的所有文件,而不管该特定目录中有多少文件,并且不会出现默认64M堆限制的“内存不足”问题

我有一段时间使用谷歌,但在纯Java中找不到这样的方法。
请帮帮我

请注意,JNI是一种可能的解决方案,但我讨厌JNI。

我知道您说过“使用默认的64M堆限制”,但让我们看看事实——您希望使用Java提供的机制在内存中保存(可能)大量项。所以,除非有什么可怕的原因,你不能,我会说增加堆是一条路要走

以下是JavaRanch的同一讨论的链接:


编辑,回应评论:我之所以说他想在内存中保存大量项目,是因为这是Java提供的唯一一种机制,可以在不使用本机接口或平台特定机制的情况下列出目录(OP说他想要“纯Java”).

在一个目录中包含300000个文件不是一个好主意-AFAIK文件系统不擅长在单个节点中包含那么多子节点。不过,这个问题很有趣

编辑:以下内容没有帮助,请参阅评论。

我认为您可以使用文件过滤器,拒绝所有文件,并在过滤器中处理它们

        new File("c:/").listFiles( new FileFilter() {
            @Override   public boolean accept(File pathname) {
                processFile();
                return false;
            }
        });

你在这里有点不走运。至少需要创建300k字符串。平均长度为8-10个字符,每个字符2个字节,最小为6Mb。添加每个字符串(8字节)的对象指针开销,您会遇到内存限制

如果您必须在一个目录中包含那么多文件(我不建议这样做,因为您的文件系统会出现问题),那么最好通过Runtime.exec运行本机进程(而不是JNI)。请记住,您将自己绑定到操作系统(ls vs dir)。您将能够以一个大字符串的形式获取文件列表,并负责将其后处理为所需内容


希望这有帮助。

对您来说唯一可能的解决方案是Java7,然后您应该使用迭代器

final Path p = FileSystems.getDefault().getPath("Yourpath");
Files.walk(p).forEach(filePath -> {
        if (Files.isRegularFile(filePath)) {
            //Do something with filePath
        }
});

如果您可以用Java7或更高版本编写代码,那么下面是一个不错的选择

Files.newDirectoryStream(路径目录)

是API的java文档


希望这能有所帮助。

64MB堆限制要求是否很难?您的代码中还有其他部分分配了很多对象吗?64MB不是一个硬限制。然而,我们希望使用java来监控一个文件夹,在这个文件夹中,我们的客户上传了大量的文件。我们不知道有多少内存是足够的。一旦你列出了所有的内存,你将对结果做什么?类似于James的调用返回一个数组。问题归结为,您是否可以在不立即分配完整数组的情况下,以某种方式获得目录中名称的迭代器。这是一个合理的问题;我不知道答案。你不能使用核心Java API。是的,我想要的正是一个FileIteratorXFS在一个目录中支持大量文件。此外,这个答案与主题相去甚远,只是检查了java.io.File的源代码。无论如何,它都会在过滤之前调用列表,所以原始问题仍然存在。是的,我希望人们在修改之前至少验证“正确”的答案。没有冒犯海报的意思。好吧,谁知道JDK程序员是这样做的?把anwer留在这里是为了警告其他人。我一直忘记JDK文件系统抽象。返回字符串文件名数组的实际列表方法是本机方法,因此在目录中检索部分文件列表的希望不大。在本文中,我发布了一个简单的示例,说明如何使用Java 7在路径的名称元素上进行迭代,而不是在目录中的文件上进行迭代。