Многочастный gzip-файл с произвольным доступом (на Java) - PullRequest
6 голосов
/ 04 августа 2009

Это может относиться к сфере "не совсем выполнимо" или "не стоит затраченных усилий", но здесь идет речь.

Я пытаюсь получить произвольный доступ к записям, хранящимся в gzip-файле из нескольких частей. В частности, интересующие меня файлы - это сжатые Heretrix Arc файлы. (Если вы не знакомы с многокомпонентными файлами gzip, спецификация gzip позволяет объединять несколько потоков gzip в один файл gzip. Они не разделяют никакой словарной информации, это просто двоичное добавление.)

Я думаю, что это должно быть возможно сделать путем поиска определенного смещения в файле, затем отсканировать байты магического заголовка gzip (то есть 0x1f8b, согласно RFC ) и попытаться читать поток gzip из следующих байтов. Проблема с этим подходом состоит в том, что те же самые байты могут появляться и внутри фактических данных, поэтому поиск этих байтов может привести к неправильной позиции, с которой можно начать чтение потока gzip. Есть ли лучший способ обработки произвольного доступа, учитывая, что смещения записей не известны априори?

Ответы [ 2 ]

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

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

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

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

1 голос
/ 04 августа 2009

Дизайн GZIP, как вы поняли, не подходит для произвольного доступа.

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

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

Это будет достаточно быстро для файлов размером менее 100 КБ. Как и предполагалось, если бы у вас было 10 файлов по 100 тыс. Каждый, это, вероятно, было бы сделано за 2 секунды на современном процессоре. Это то, что я имею в виду под «довольно быстро». Но только вы знаете требования к вашему заявлению.

Есть ли у вас класс GZipInputStream? Если это так, вы на полпути туда.

...