当我列出包含300,000个带Java文件的目录的文件时,会发生内存不足。
String[] fileNames = file.list();
我想要的是一种方法,可以逐步列出目录的所有文件,无论该特定目录中有多少文件,并且没有默认64M堆限制的“内存不足”问题。
我有谷歌一段时间,并没有在纯Java中找到这样的方式。
请帮帮我!!
注意,JNI是一种可能的解决方案,但我讨厌JNI。
当我列出包含300,000个带Java文件的目录的文件时,会发生内存不足。
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)。您将能够将文件列表作为一个大字符串获取,并负责将其后处理为您想要的内容。
希望这可以帮助。
在目录中有30万个文件并不是一个好主意 - AFAIK文件系统不擅长在单个节点中拥有那么多子节点。但有趣的问题。
编辑:以下没有帮助,看到评论。
我认为你可以使用FileFilter,拒绝所有文件,并在过滤器中处理它们。
new File("c:/").listFiles( new FileFilter() {
@Override public boolean accept(File pathname) {
processFile();
return false;
}
});