Эффективный метод чтения строк String из файла

Предполагая, что у меня есть файл записей журнала размером 15 ГБ, и я хотел бы перебрать \n завершенных строк из этого файла. Какая стандартная библиотека Java / третьи стороны предоставляют чистый интерфейс для этой операции.

Обратите внимание, что я ищу решение на основе NIO, предпочтительно с использованием метода доступа к файлам с отображением памяти, как показано в этом вопросе Как мне создать строку Java из содержимого файла? было бы идеальным решением, если бы оно не загружало весь байтовый буфер в память перед возвратом нового экземпляра буфера String(). Этот подход не работает в этом случае из-за размера ввода.

Спасибо,
Максим.


person Maxim Veksler    schedule 06.02.2011    source источник


Ответы (3)


Рассматривали ли вы возможность использования BufferedReader? Из документации:

Читает текст из потока ввода символов, буферизуя символы, чтобы обеспечить эффективное чтение символов, массивов и строк.

Он имеет чистый интерфейс для получения строк с \n-завершением (BufferedReader.readLine()) и должен быть довольно эффективным, поскольку он буферизован.

person aioobe    schedule 06.02.2011
comment
+1: узким местом, вероятно, будет время, необходимое для чтения файла размером 15 ГБ с диска. Как вы это сделаете, вряд ли имеет большое значение. Так что лучше всего, чтобы это было просто. - person Peter Lawrey; 06.02.2011

ИМХО никаких NIO для этой задачи не нужно. Используйте обычный BufferedReader:

BufferedReader reader = new BufferedReader(new FileReader("myfile.log"));

Затем пользователь reader.readLine().

person AlexR    schedule 06.02.2011

Он не основан на NIO, но я бы взглянул на метод Guava CharStreams.readLines(InputSupplier, LineProcessor). Он делает то, что вы хотите, я бы сказал:

File file = ...
Foo result = CharStreams.readLines(Files.newReaderSupplier(file, Charsets.UTF_8),
    new LineProcessor<Foo>() {
      public boolean processLine(String line) {
        // do stuff for this line
        return true; // or false if you want to stop processing here
      }

      public Foo getResult() {
        return result; // if you create some result when processing the lines
      }
    });

При этом используется обратный вызов, позволяющий последовательно обрабатывать каждую строку в файле. Он не загружает следующую строку в память, пока вы не закончите обработку текущей. Если вы не хотите создавать какой-то один объект результата при чтении строк, вы можете просто использовать LineProcessor<Void> и заставить getResult() возвращать null.

person ColinD    schedule 06.02.2011