Вернитесь 'n' строк в файл, используя Stream.lines - PullRequest
0 голосов
/ 04 декабря 2018

Мне нужно создать приложение, которое сканирует большое количество файлов.Эти файлы содержат блоки с некоторыми данными о сеансах, в которых каждая строка имеет различное значение.Например: "= ID: 39487".

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

Мне было интересно, возможно ли что-то подобное с помощью Stream API (Files)?Или, возможно, лучший вопрос, есть ли лучший способ подойти к этому?

Stream<String> lines = Files.lines(Paths.get(file.getName()));
Iterator<String> search = lines.iterator();

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Попробуй мою библиотеку. abacus-util

try(Reader reader = new FileReader(yourFile)) {
    StreamEx.of(reader)
        .sliding(n, n, ArrayList::new)
        .filter(l -> l.get(l.size() - 1).contains("=ID: 39487"))
        ./* then do your work */
}

Независимо от размера вашего файла.пока n - это небольшое число, а не миллионы

0 голосов
/ 04 декабря 2018

Вы не можете произвольно читать вперед и назад через файл с помощью одного и того же устройства чтения (независимо от того, используете ли вы потоки, итераторы или просто BufferedReader.)

Если вам нужно:

  • m строк до заданной строки
  • n строк после заданной строки
  • Вы не знаете значения m и n заранее, пока вы не достигнете этой строки

... тогда у вас по существу есть три варианта:

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

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

В качестве альтернативы, если вы можете гарантировать, что значения n и m ниже определенного значения, иэто значение разумного размера - вы также можете просто сохранить определенное количество строк в буфере при обработке файла и прочитать этот буфер, когда вам нужно прочитать строки «назад».

...