Как иметь дело с большими строками и ограниченной памятью

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

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

Что я должен сделать, чтобы помешать памяти переполняться?

6
задан Anthony Forloney 27 January 2010 в 16:07
поделиться

4 ответа

Вы должны использовать BufferedInPutReader вместо того, чтобы сохранить все это в одну большую строку.

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

6
ответ дан 8 December 2019 в 12:59
поделиться
121 --- 1568395-

Другие предложили для чтения и обработки порций вашего файла одновременно. Отказ Если возможно, один из тех способов будет лучше.

Тем не менее, если это невозможно, и вы можете загрузить строку , вначале в память, поскольку вы указываете, но это позже анализ этой строки, которая создает проблемы, вы сможете использовать подпункты. В Java настроенные карты сверху оригинала Array Char и просто используют память для базы объекта , а затем начало и длина INT указателей.

Итак, когда вы найдете часть строки, которую вы хотите сохранить отдельно, используйте что-то вроде:

String piece = largeString.substring(foundStart, foundEnd);

, если вы вместо этого или код, которые внутренне используют это, то использование памяти значительно увеличивается:

new String(largeString.substring(foundStart, foundEnd));

Примечание. Что вы должны использовать string.substring () с осторожностью по этому мнению по этой причине. Вы можете иметь очень большую строку, из которой вы берете подстроку, а затем отбросьте ссылку на исходную строку. Проблема в том, что подстрока все еще ссылается на оригинальные крупные массив . GC не отпустит то, пока подстрока также не будет удалена. В таких случаях, как это полезно фактически использовать новую строку (...) , чтобы обеспечить отброс неиспользованного большого массива в GC (это одно из немногих случаев, когда вы когда-либо должны использовать Новая строка (...) ).

Другая техника, если вы ожидаете, что у вас есть много маленьких струн, и они могут иметь одинаковые значения, но приходят от внешнего источника (например, файл), является использование .intern () После создания новой строки.

Примечание. Это зависит от реализации строки , которую вы действительно не должны быть в курсе, но на практике для крупных приложений иногда вы должны полагаться на это знание. Имейте в виду, что будущие версии Java могут изменить это (хотя и вряд ли).

5
ответ дан 8 December 2019 в 12:59
поделиться

Вы должны просмотреть свой алгоритм для решения большинства больших данных. Вы должны обработать Chunk-by-chank это данные или использовать случайный доступ к файлам без хранения данных в памяти. Например, вы можете использовать StringTokedizer или StreamTokerizer, как сказал @zombies. Вы можете увидеть методы Parser-Lexer: когда анализатор анализирует некоторое выражение, он просит Lexer прочитать следующий лексем (токены), но не читает весь входной поток одновременно.

1
ответ дан 8 December 2019 в 12:59
поделиться

Если вы можете немного ослабить свои требования, вы можете реализовать java.lang.CharSequence , подкрепленный вашим файлом.

CharSequence поддерживается во многих местах JDK (Строка - это CharSequence) . Таким образом, это хорошая альтернатива реализации на основе Reader.

6
ответ дан 8 December 2019 в 12:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: