GZIP-поток с произвольным доступом - PullRequest
12 голосов
/ 27 марта 2010

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

Любой совет?

Мои мысли были:

  • Взломайте существующую реализацию gzip и сериализуйте ее состояние декомпрессора, скажем, на 1 мегабайт сжатых данных. Затем, чтобы сделать произвольный доступ, десериализовать состояние декомпрессора и прочитать с границы мегабайта. Это кажется сложным, особенно если учесть, что я работаю с Java и не могу найти реализацию gzip на чистой Java: (
  • Повторно сожмите файл кусками по 1 Мб и сделайте то же самое, что и выше. Недостатком этого является удвоение необходимого дискового пространства.
  • Напишите простой синтаксический анализатор формата gzip, который не выполняет распаковку, а только обнаруживает и индексирует границы блоков (если есть даже блоки: я еще не читал описание формата gzip)

Ответы [ 3 ]

6 голосов
/ 27 марта 2010

Посмотрите по этой ссылке (пример кода C).

/* zran.c -- example of zlib/gzip stream indexing and random access
...

Gzip - это просто zlib с конвертом.

4 голосов
/ 22 апреля 2010

Формат файла BGZF , совместимый с GZIP, был разработан биологами.

(...) Преимущество BGZF по сравнению с обычным GZIP является то, что BGZF позволяет искать, не имея сканировать весь файл до искомая позиция.

В http://picard.svn.sourceforge.net/viewvc/picard/trunk/src/java/net/sf/samtools/util/, посмотрите на BlockCompressedOutputStream и BlockCompressedInputStream.java

0 голосов
/ 27 марта 2010

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

Возможно, вы имеете в виду, что у вас нет контроля над вводом, и поэтому он удвоится.

Если вы можете сделать это, я представляю, что моделирую его как класс CompressedFileStream, который использует в качестве резервного хранилища серию 1-мегабайтных gzip-файлов. При чтении Seek () в потоке перемещается к соответствующему BLOB-объекту и распаковывается. Чтение () после конца большого двоичного объекта приведет к тому, что поток откроет следующий большой двоичный объект.

ps: GZIP описан в IETF RFC 1952 , но он использует DEFLATE для формата сжатия. Не было бы никакой причины использовать разработку GZIP, если бы вы реализовали этот класс CompressedFileStream, как я его себе представлял.

...