Как очистить все переменные в длинном цикле for, чтобы программа не исчерпала память?

1

У меня есть цикл for который работает 20 000 раз с циклом for внутри него, который также работает в 20 000 раз, что составляет до 400 миллионов.

в цикле for он добавляет 20 000 номеров в строку, а затем записывает эту строку в txt файл. после записи строка устанавливается пустым следующим образом: String Name = "";

поэтому я получу в общей сложности 20 000 текстовых файлов с каждыми 20 000 номерами в нем.

теперь, если цикл for создал около 200 файлов, он начинает исчерпывать память и в конечном итоге падает.

как я могу избежать этого?

- вот код -

public static void mapScanner()
{

    String content = "";

    for(int z = -10000; z < 10000; z++)
    {
        Util.CreateFile(z);
        for(int x = -10000; x < 10000; x++)
        {
            Block block = Bukkit.getServer().getWorld("world").getBlockAt(x, Bukkit.getServer().getWorld("world").getHighestBlockYAt(x, z) -1, z);

            if(block.getType() != Material.AIR)
            {
                content += Blocks.blockID(block.getType());
            }
        }

        try 
        {
            File file = new File("plugins/Map/" + z + ".txt");
            System.out.println(content);
            FileWriter fw = new FileWriter(file.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(content);
            bw.close();
            content = "";

            System.out.println("The file : " + z + ".txt has been created and written.");

        } 
        catch (IOException e) 
        {
            e.printStackTrace();
        }

    }
}

block.getType() просто возвращает число.


Общий код:

for(int x = 0; x < 20000; x++)
    {
        String content = "";
        CreateFile(x);
        for(int z = 0; z < 20000; z++)
        {

            content += "1";

        }

        try 
        {
            File file = new File("Map/" + x + ".txt");
            FileWriter fw = new FileWriter(file.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(content);
            bw.close();

            //System.out.println("The file : " + x + ".txt has been created and written.");

        } 
        catch (IOException e) 
        {
            e.printStackTrace();
        }

    }

public static void CreateFile(int z) {

    File file = new File("Map/" + z + ".txt");
    boolean fileCreated = false;
    try {
        fileCreated = file.createNewFile();
    } catch (IOException ioe) {
        //System.out.println("Error while creating empty file: " + ioe);
    }

    if (fileCreated) {
        //System.out.println("Created empty file: " + file.getPath());
    } else {
        //System.out.println("Failed to create empty file: " + file.getPath());
    }

}
  • 2
    Было бы намного легче помочь вам, если бы вы показали нам код, а не просто описали его. Например, если вы используете многократную конкатенацию строк, то достаточно использовать StringBuilder , чтобы значительно уменьшить отток GC. Но это звучит так, как будто все должно быть в порядке, так как все должно быть подходящим для сбора. Короткая , но полная программа демонстрирует проблему будет сделать это намного проще , чтобы помочь вам.
  • 0
    что такое Util.CreateFile ?
Показать ещё 15 комментариев
Теги:
for-loop
loops
memory
crash

2 ответа

2

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

Один из способов сделать это, это написать прямо в файл, поэтому не нужно держать строку в памяти.

Извините за мою грамматику, я не умею писать...

Попробуйте что-то вроде этого:

public static void mapScanner()
{

String content = "";

for(int z = -10000; z < 10000; z++)
{
    File file = new File("plugins/Map/" + z + ".txt");
    // if file doesn't exists, then create it, this inside another try.
    if (!file.exists()) {
        file.createNewFile();
    }

    FileOutputStream fw = new FileOutputStream(file);
    OutputStream bw = new BufferedOutputStream(fw);

    for(int x = -10000; x < 10000; x++)
    {
        Block block = Bukkit.getServer().getWorld("world").getBlockAt(x, Bukkit.getServer().getWorld("world").getHighestBlockYAt(x, z) -1, z);

        if(block.getType() != Material.AIR)
        {
            string temp = Blocks.blockID(block.getType());
            System.out.println(temp);
            bw.write(temp.getBytes());
        }
    }

    try 
    {
        // Close all
        bw.flush();
        bw.close();
        fw.close();
        file.close();
        System.out.println("The file : " + z + ".txt has been created and written.");
    } 
    catch (IOException e) 
    {
        e.printStackTrace();
    }

 }
}
  • 0
    хорошо я храню значения в строке, потому что он не имеет всех значений в начале цикла for, но получает значения внутри. если он содержит все значения, хранящиеся в строке, он записывает его. это потому, что иначе мне пришлось бы использовать 400 миллионов записей
  • 0
    @NielsPeeren - Вы используете буферный писатель, так что это не имеет значения. Эти записи на самом деле просто добавляет в буфер
Показать ещё 10 комментариев
1

замените String content = "" на StringBuilder content = new StringBuilder() и content += Blocks.blockID(block.getType()) с content.append(Blocks.blockID(block.getType()))

это должно заставлять вашу петлю работать намного быстрее. Я сомневаюсь, что это поможет с вашей проблемой OutOfMemory.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню