Прыгать на строку и читать ее - PullRequest
3 голосов
/ 04 ноября 2010

Мне нужно работать с большими файлами (много ГБ) и мне нужны быстрые поиски для извлечения определенных строк по запросу.

Идея состояла в том, чтобы сохранить отображение:

some_key -> byte_location

Гдерасположение байта показывает, где в файле начинается строка.

Редактировать: вопрос немного изменился:

Сначала я использовал:

FileInputStream stream = new FileInputStream(file);
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
FileChannel channel = stream.getChannel();

Я заметил, что FileChannel.position() не будет возвращать точную позицию, где читатель читает в данный момент, потому что это читатель с буферизацией.Он читает фрагменты заданного размера (16 КБ здесь), поэтому то, что я получаю из FileChannel, кратно 16 КБ, а не точной позиции, где читатель фактически читает.

PS: файл находится в UTF-8

Ответы [ 2 ]

3 голосов
/ 04 ноября 2010

Любая причина не создавать FileInputStream, позвонить stream.skip(pos), а затем создать InputStreamReader вокруг этого и BufferedReader вокруг InputStreamReader?

2 голосов
/ 04 ноября 2010

Я бы попробовал что-то вроде этого:

    RandomAccessFile raf = new RandomAccessFile(file);
    ...
    raf.seek(position);
    raf.readLine();
    ...

Проблема в том, что readLine() превращает каждый байт в символ с верхними 8 битами, равными нулю.Это нормально, если ваш файл ASCII или Latin-1, но проблематично для UTF-8.

Однако, если вы собираетесь использовать RandomAccessFile для записи файла, вы можете использовать readUTF() и writeUTF() для чтения и записи «строк», закодированных как измененные строки UTF-8.

FOLLOWUP

черт побери...втф-8 символов прикручены

Да ... см. выше.

Еще одна идея для работы с UTF-8 с RandomAccessFile:

  1. искать в нужной позиции,
  2. использовать метод readFully(byte[]) для чтения группы байтов в byte[],
  3. locate pos == положение конца строки вбуфер,
  4. , если не найден, прочитать дополнительные байты, объединить и перейти к шагу 2.
  5. , если найден, использовать new String(bytes, 0, pos, UTF-8) для преобразования в строку Java.

Это более громоздко, чем использование readLine(), но оно должно быть быстрее, чем использование FileInputStream и skip() при чтении нескольких строк из файлов в случайном порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...