Я сейчас пишу что-то, что должно обрабатывать очень большие текстовые файлы (по крайней мере, несколько ГиБ). Здесь нужно (и это исправлено):
- На основе CSV, в соответствии с RFC 4180, за исключением встроенных разрывов строк
- произвольный доступ для чтения к строкам, хотя в основном построчно и ближе к концу
- добавление строк в конце
- (смена строк). Очевидно, что это требует перезаписи остальной части файла, это тоже редко, поэтому в данный момент не особо важно
Размер файла запрещает хранить его полностью в памяти (что также нежелательно, поскольку при добавлении изменения должны сохраняться как можно скорее).
Я думал об использовании отображенной в памяти области в качестве окна в файл, который перемещается, если запрашивается строка вне его диапазона. Конечно, на этом этапе у меня все еще нет абстракции выше уровня байтов. Чтобы реально работать с содержимым, у меня есть CharsetDecoder
, дающий мне CharBuffer
. Теперь проблема в том, что я могу справиться со строками текста, вероятно, просто отлично в CharBuffer
, но мне также нужно знать смещение байтов этой строки в файле (чтобы сохранить кэш строковых индексов и смещений, чтобы я не Чтобы найти конкретную строку, снова нужно отсканировать файл с самого начала.
Есть ли способ сопоставить смещения в CharBuffer
со смещениями в ByteBuffer
? Это очевидно тривиально с ASCII или ISO-8859- *, менее с UTF-8 и с ISO 2022 или BOCU-1 все станет совершенно безобразно (не то, чтобы я действительно ожидал, что последние два, но UTF-8 должен быть здесь по умолчанию здесь - и до сих пор создает проблемы).
Полагаю, я мог бы просто преобразовать часть CharBuffer
в байты снова и использовать длину. Либо это работает, либо у меня возникают проблемы с диакритическими знаками, и в этом случае я, вероятно, могу поручить использование NFC или NFD, чтобы гарантировать, что текст всегда однозначно закодирован.
Тем не менее, мне интересно, если это даже путь сюда. Есть ли лучшие варианты?
ETA: Некоторые ответы на общие вопросы и предложения здесь:
Это хранилище данных для прогонов симуляции, предназначенное для локальной альтернативы полноценной базе данных. У нас есть и базы данных, и они используются, но для случаев, когда они недоступны или неприменимы, мы этого хотим.
Я также поддерживаю только подмножество CSV (без встроенных разрывов строк), но пока это нормально. Проблемные моменты здесь в значительной степени заключаются в том, что я не могу предсказать, насколько длинные линии, и, следовательно, необходимо создать приблизительную карту файла.
Что касается того, что я обрисовал в общих чертах выше: я размышлял о том, что могу легко определить конец строки на уровне символов (U + 000D + U + 000A), но я не хотел предполагать, что это выглядит как 0A 0D
на уровне байтов (который уже не срабатывает для UTF-16, например, где это либо 0D 00 0A 00
, либо 00 0D 00 0A
). Я думал, что смогу изменить кодировку символов, не используя жесткие детали кодировки, которую я сейчас использую. Но я думаю, что я мог бы просто придерживаться UTF-8 и делать все остальное. Хотя как-то нехорошо.