поиск в сжатом отсортированном файле фиксированной ширины

Предположим, у меня есть обычный файл фиксированной ширины, который отсортирован по одному из полей. Учитывая, что я знаю длину записей, я могу использовать lseek для реализации двоичного поиска для поиска записей с полями, соответствующими заданному значению, без необходимости читать весь файл.

Теперь сложность в том, что файл заархивирован. Можно ли это сделать без полного накачивания файла? Если не с помощью gzip. есть ли какое-либо сжатие, поддерживающее такое поведение?


person frankc    schedule 23.04.2010    source источник


Ответы (6)


Это совершенно невозможно с файлом, сжатым с помощью zip и производных. Они основаны на скользящем окне словаря, как правило, с каким-то сжатием на основе буфера наиболее значимых бит выходных кодов поверх этого. Суть в том, что определенная последовательность байтов в zip-файле бессмысленна без контекста.

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

person 500 - Internal Server Error    schedule 24.04.2010

Формат файла bzip2 состоит из нескольких независимо сжатых блоков. Если вы хотите поддерживать индекс вместе с файлом bzip2, вы можете знать, где искать.

Примечание: это дубликаты вопросов:

Они отвечают на тот же вопрос, но также идентифицируют BGZF как gzip-совместимый выходной формат с точками синхронизации, вставленными для сброса состояния сжатия.

person Liudvikas Bukys    schedule 03.05.2010
comment
Другой формат файла с возможностью поиска, совместимый с gzip, - это idzip. Подходит, если вам нравится Python. - person Ivo Danihelka; 06.01.2011

Практически все известные мне алгоритмы сжатия работают в блочном режиме, то есть случайный поиск невозможен. Даже LZMA, который не использует исходный словарь, требует последовательной декомпрессии.

Сжатие потока обычно означает адаптивное сжатие с потерями с некоторым ключом, который сбрасывает состояние (или фактически разрезает на блоки). Детали более сложные.

Вот несколько идей, как решить эту проблему:

  • Создайте индекс. Например, когда вы открываете ZIP-архив, вы можете видеть все файлы в нем.
  • Разрежьте ваш сжатый файл на блоки, а затем используйте двоичный поиск в каждом блоке (фактически аналогично первому)
  • Распаковать в памяти, но на самом деле отбрасывать все данные, пока не найдете начало данных, которые вы ищете.

Последний способ подходит для небольших сжатых файлов, а блочный метод - для сжатых файлов большего размера. Вы можете смешать то и другое.

PS: Исправлено с помощью ввода, не означает, что сжатый файл будет исправлен с помощью. Так что это довольно бесполезная информация.

person Wernight    schedule 27.04.2010

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

person Mark Ransom    schedule 27.04.2010

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

person wump    schedule 03.05.2010

вам нужно сжатие с возможностью поиска; у dict-сервера есть dictzip, формат которого совместим с gzip, поскольку он хранит его для поиска в расширении gzip в заголовке, а в наборе для поиска есть sgzip, которого нет, поскольку он хранит длину блоков в начале каждого из блоков

person Dan D.    schedule 05.08.2010