OutOfMemory, когда файлы списка в каталоге
Когда я перечисляю файлы каталога с 300 000 файлов с Java, происходит нехватка памяти.
String[] fileNames = file.list();
То, что я хочу, это способ, который может перечислить все файлы каталога постепенно, независимо от того, сколько файлов в этом конкретном каталоге и не будет иметь проблемы с "нехваткой памяти" с максимальным размером кучи по умолчанию 64 МБ.
У меня есть Google некоторое время, и я не могу найти такой путь в чистой Java.
Пожалуйста, помогите мне!
Примечание. JNI - это возможное решение, но я ненавижу JNI.
Ответы
Ответ 1
Я знаю, что вы сказали "с пределом кучи по умолчанию 64M", но давайте посмотрим на факты - вы хотите удержать (потенциально) большое количество элементов в памяти, используя механизмы, предоставленные вам Java. Итак, если нет какой-то серьезной причины, по которой вы не можете, я бы сказал, что увеличение кучи - это путь.
Вот ссылка на одно и то же обсуждение в JavaRanch: http://www.coderanch.com/t/381939/Java-General/java/iterate-over-files-directory
Изменить, в ответ на комментарий: причина, по которой я сказал, что он хочет хранить большое количество элементов в памяти, состоит в том, что это единственный механизм, который Java предоставляет для перечисления каталога без использования собственного интерфейса или механизмы, специфичные для платформы (и OP сказал, что ему нужна "чистая Java" ).
Ответ 2
Единственное возможное решение для вас - это Java7, а затем вы можете использовать итератор.
final Path p = FileSystems.getDefault().getPath("Yourpath");
Files.walk(p).forEach(filePath -> {
if (Files.isRegularFile(filePath)) {
//Do something with filePath
}
});
Ответ 3
Вам здесь немного не повезло. По крайней мере, потребуется создать 300k строк. Средняя длина 8-10 char и 2 байта за char составляет минимум 6 Мб. Добавьте служебную нагрузку указателя объекта на строку (8 байт), и вы запуститесь в свой предел памяти.
Если вы абсолютно должны иметь такое количество файлов в одном каталоге, которое я бы не рекомендовал, так как ваша файловая система будет иметь проблемы, лучше всего запустить собственный процесс (не JNI) через Runtime.exec. Имейте в виду, что вы привяжете себя к ОС (ls vs dir). Вы сможете получить список файлов в виде одной большой строки и нести ответственность за последующую обработку его в то, что вы хотите.
Надеюсь, что это поможет.
Ответ 4
Наличие 300 000 файлов в каталоге не является хорошей идеей - файловые системы AFAIK не очень хороши в том, что у многих подузлов есть только один node. Интересный вопрос, тем не менее.
РЕДАКТИРОВАТЬ: ПОСЛЕДУЮЩИЕ НЕ ПОМОГАЕТ, см. комментарии.
Я думаю, вы могли бы использовать FileFilter, отклонять все файлы и обрабатывать их в фильтре.
new File("c:/").listFiles( new FileFilter() {
@Override public boolean accept(File pathname) {
processFile();
return false;
}
});
Ответ 5
Если вы можете написать свой код в Java 7 или выше, то подходящим вариантом является следующий.
Files.newDirectoryStream(Path dir)
Здесь - это java-документ для API.
Надеюсь, что это поможет.