Exception in thread “main” java.lang.OutOfMemoryError: Java heap space при сканировании большого количества папок

298
10 февраля 2017, 03:11

Пытаюсь выполнить сканирование проекта, на предмет поиска в нем файлов содержащих слово заглушка. Файлы в кодировке UTF-16. Но когда парсер доходит до 1017 файла, все падает с сообщением

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space.

Подскажите, как этого избежать этого

import java.io.*;
import java.util.Scanner;
public class FolderScanerV2 {
public static void FolderScaner(File file) throws Exception {
    if (file.isDirectory()) {
        File[] directory = file.listFiles();
        for (File enter : directory) {
            if ((enter.isFile() & enter.getCanonicalPath().contains("txt"))) {
                FileScaner(enter);
            } else {
                FolderScaner(enter);
            }
        }
    }
}
public static void FileScaner(File file) throws Exception {
    BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file.getAbsolutePath()), "UTF-16"));
    Scanner text = new Scanner(in);
    while (text.hasNext()) {
        if(text.next().contains("Заглушка")) {
            System.out.println("Заглушка" + " " + file.getCanonicalPath());
        }
    }
}
public static void main(String[] args) {
    String path = new String();
    Scanner inpunt = new Scanner(System.in);
    System.out.println("Введи путь к файлу или папке");
    path = inpunt.nextLine(); // получаем путь к файлу(строку)
    File dir = new File(path);
    try {
        FolderScaner(dir);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
}
Answer 1

дополнительно к ответу @iksuy рекомендую использовать

        try(Scanner text = new Scanner(in);) { // такая конструкция позволяет закрывать потоки в конце автоматически 
            while (text.hasNext()) {
                if (text.next().contains("Заглушка")) {
                    System.out.println("Заглушка" + " " + file.getCanonicalPath());
                }
            }
        }

если использовать Java 8 Stream API, то можно легко распараллелить операции

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
public class Main {
    public static void main(java.lang.String[] args) {
        File searchDir = new File("C:\\New folder");
        Collection<File> files = FileUtils.listFiles(searchDir, new String[]{"txt"}, true); // позволяет сканировать директории и возвращает файлы по маске
        java.util.List<String> res = files // берем наш список 
                .parallelStream()          // в параллель выполняем операции 
                .filter(f -> isContains(f)) // по фильтру выбираем те файлы, которые содержат слово 
                .map(File::getAbsolutePath) // для тех файлов, которые прошли условие,  берем полный путь 
                .collect(Collectors.toList()); // сохраняем в массив 
        System.out.println(res.toString()); // печатаем результат 
    }

    public static boolean isContains(File f) {
        try (
                BufferedReader in =
                        new BufferedReader(new InputStreamReader(
                                new FileInputStream(f.getAbsolutePath()), "UTF-8"));
                Scanner text = new Scanner(in);) {
            while (text.hasNext()) {
                if (text.next().contains("Заглушка")) {
                    return true;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

}
Answer 2

Ресурсы нужно освобождать. У вас все файлы открываются и не закрываются, остаются висеть в памяти, она пухнет и в итоге ошибка происходит.

Scanner text = new Scanner(in);
//...
//...
text.close(); //Закроет переданный BufferedReader
READ ALSO
Создание REST API Java EE

Создание REST API Java EE

Дано: встала задача написания простенького REST API, состоящего буквально из нескольких методовНа вход подаем несколько параметров, на выходе...

449
Возвращение данных по нажатию кнопки в другом классе

Возвращение данных по нажатию кнопки в другом классе

У меня есть адаптер ListView где по нажатию на элемент я хочу показать диалогДля этого я создал класс который показывает диалог с кнопкой

300
перерисовка view по таймеру

перерисовка view по таймеру

ЗдравствуйтеИмеется кастомный view

326
Архитектура web torrent клиента

Архитектура web torrent клиента

Подскажите как правильно организовать локальную торрент качалку с веб интервейсомСам торрент клиент уже написан

255