StringBuilder.append из памяти - PullRequest
       32

StringBuilder.append из памяти

0 голосов
/ 19 февраля 2020

Я использую StringBuilder.append () для анализа и обработки файла следующим образом:

        StringBuilder csvString = new StringBuilder();

        bufferedReader.lines().filter(line -> !line.startsWith(HASH) && !line.isEmpty()).map(line -> line.trim())
                .forEachOrdered(line -> csvString.append(line).append(System.lineSeparator()));

        int startOfFileTagIndex = csvString.indexOf(START_OF_FILE_TAG);

        int startOfFieldsTagIndex = csvString.indexOf(START_OF_FIELDS_TAG, startOfFileTagIndex);
        int endOfFieldsTagIndex = csvString.indexOf(END_OF_FIELDS_TAG, startOfFieldsTagIndex);

        int startOfDataTagIndex = csvString.indexOf(START_OF_DATA_TAG, endOfFieldsTagIndex);
        int endOfDataTagIndex = csvString.indexOf(END_OF_DATA_TAG, startOfDataTagIndex);

        int endOfFileTagIndex = csvString.indexOf(END_OF_FILE_TAG, endOfDataTagIndex);

        int timeStartedIndex = csvString.indexOf("TIMESTARTED", endOfFieldsTagIndex);
        int dataRecordsIndex = csvString.indexOf("DATARECORDS", endOfDataTagIndex);
        int timeFinishedIndex = csvString.indexOf("TIMEFINISHED", endOfDataTagIndex);

        if (startOfFileTagIndex != 0 || startOfFieldsTagIndex == -1 || endOfFieldsTagIndex == -1
                || startOfDataTagIndex == -1 || endOfDataTagIndex == -1 || endOfFileTagIndex == -1) {

            log.error("not in correct format");

            throw new Exception("not in correct format.");
        }

Проблема в том, что когда файл достаточно велик, я получаю исключение outofmemoryexception. Можете ли вы помочь мне преобразовать мой код, чтобы избежать этого исключения с большими файлами?

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

1 Ответ

1 голос
/ 19 февраля 2020

Кажется, OOM связано с тем, что вы храните все строки в StringBuilder. Если в файле слишком много строк, он займет огромный объем памяти и может привести к OOM.

Стратегия, позволяющая избежать этого, зависит от того, что вы делаете с добавленными строками. Как я вижу в вашем коде, вы только пытаетесь проверить структуру входного файла. В этом случае вам не нужно хранить все строки в экземпляре StringBuilder. Вместо этого

  1. Имеется несколько int с для хранения каждого интересующего вас индекса (или массив int с)
  2. Вместо добавления строки в StringBuilder, найдите наличие «тега» или «индекса», который вы ищете, и сохраните его в назначенной переменной int.
  3. Наконец, проверка, которую вы уже делаете, может потребоваться в разделе go изменение для проверки не как -1, а относительно других индексов. (Это вы в настоящее время достигаете, используя начальный индекс в вызове indexOf().)
  4. Если существует риск того, что тег пересекает строки, вы, возможно, не сможете использовать потоки, но вам придется используйте простую for l oop, в которой сохраните несколько предыдущих строк, добавьте их и проверьте. (Только одна идея; у вас может быть лучшая.)
...