OutOfMemory, когда список файлов в каталоге - PullRequest
11 голосов
/ 13 января 2010

Когда я перечисляю файлы каталога, в котором есть 300 000 файлов с Java, возникает нехватка памяти.

String[] fileNames = file.list();

То, что я хочу, - это способ, с помощью которого можно постепенно выводить список всех файлов каталога независимо от количества файлов в этом конкретном каталоге и не иметь проблемы «нехватки памяти» со стандартным пределом кучи 64M.

У меня есть Google некоторое время, и я не могу найти такой путь в чистой Java.
Пожалуйста, помогите мне !!

Заметьте, JNI - это возможное решение, но я ненавижу JNI.

Ответы [ 5 ]

5 голосов
/ 13 января 2010

Я знаю, что вы сказали "с предельным размером кучи в 64 МБ", но давайте посмотрим на факты - вы хотите хранить (потенциально) большое количество элементов в памяти, используя механизмы, предоставленные вам Java. Так что, если нет какой-то серьезной причины, по которой вы не можете, я бы сказал, что увеличение кучи - это путь.

Вот ссылка на то же обсуждение на JavaRanch: http://www.coderanch.com/t/381939/Java-General/java/iterate-over-files-directory

Редактировать в ответ на комментарий: причина, по которой я сказал, что он хочет хранить в памяти большое количество элементов, заключается в том, что это единственный механизм, который Java предоставляет для вывода каталога без использования собственного интерфейса или механизмы, специфичные для платформы (и ОП сказал, что хочет «чистую Java»).

4 голосов
/ 23 июля 2012

Единственное возможное решение для вас - это Java7, и тогда вы должны использовать итератор.

final Path p = FileSystems.getDefault().getPath("Yourpath");
Files.walk(p).forEach(filePath -> {
        if (Files.isRegularFile(filePath)) {
            //Do something with filePath
        }
});
2 голосов
/ 13 января 2010

Вам немного не повезло. По крайней мере, нужно будет создать 300 тыс. Строк. При средней длине 8-10 символов и 2 байта на символ минимум 6 МБ. Добавьте указатель объекта на строку (8 байт), и вы достигнете предела памяти.

Если вам абсолютно необходимо иметь столько файлов в одном каталоге, что я бы не рекомендовал, так как у вашей файловой системы будут проблемы, лучше всего запустить собственный процесс (не JNI) через Runtime.exec. Имейте в виду, что вы будете привязаны к ОС (ls vs dir). Вы сможете получить список файлов в виде одной большой строки и будете нести ответственность за последующую обработку его в соответствии с вашими желаниями.

Надеюсь, это поможет.

1 голос
/ 13 января 2010

Наличие 300 000 файлов в каталоге не является хорошей идеей - файловые системы AFAIK не способны иметь такое количество подузлов в одном узле. Интересный вопрос, хотя.

РЕДАКТИРОВАТЬ: СЛЕДУЮЩАЯ НЕ ПОМОГАЕТ, см. Комментарии.

Я думаю, вы могли бы использовать FileFilter, отклонить все файлы и обработать их в фильтре.

        new File("c:/").listFiles( new FileFilter() {
            @Override   public boolean accept(File pathname) {
                processFile();
                return false;
            }
        });
0 голосов
/ 01 июля 2016

Если вы можете написать свой код на Java 7 или более поздней версии, тогда хорошим вариантом будет следующее.

Files.newDirectoryStream (путь к каталогу)

Здесь - документ Java для API.

Надеюсь, это поможет.

...