Форматы сжатия с хорошей поддержкой случайного доступа в архивах?

Это похоже на предыдущий вопрос, но ответы там не удовлетворяют мои потребности, и мой вопрос немного отличается:

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

Но когда файлы сжимаются, все становится сложнее. Недавно я узнал о параметре zlib Z_FULL_FLUSH, который можно использовать во время сжатия для вставки "точек синхронизации" в сжатый вывод (затем inflateSync() может начать чтение из различных точек в файле). Это нормально, хотя файлы, которые у меня уже есть, нужно было бы повторно сжать, чтобы добавить эту функцию (и странно, что у gzip нет опции для этого, но я готов написать свою собственную программу сжатия, если необходимо).

Из одного источника кажется, что даже Z_FULL_FLUSH не является идеальным решением... он не только не поддерживается всеми архивами gzip, но и сама идея обнаружения точек синхронизации в архивах может давать ложные срабатывания (либо по совпадению с магическим числом для точки синхронизации или из-за того, что Z_SYNC_FLUSH также создает точки синхронизации, но они не могут использоваться для произвольного доступа).

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

Изменить: Как я уже говорил, я хочу сделать бинарный поиск в сжатых данных. Мне не нужно искать конкретную (несжатую) позицию - только искать с некоторой грубой детализацией в сжатом файле. Мне просто нужна поддержка для чего-то вроде "Распакуйте данные, начиная примерно с 50% (25%, 12,5% и т.д.) Пути в этот сжатый файл".

Ответ 1

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

Например, сжатые файлы bzip2 состоят из независимых сжатых блоков размером < 1MB без сжатия, которые ограничены последовательностями магических байтов, поэтому вы можете проанализировать файл bzip2, получить границы блоков, а затем просто расстегнуть правый блок, Это потребует некоторой индексации, чтобы помнить, где начинаются блоки.

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

Ответ 2

Взгляните на dictzip. Он совместим с gzip и позволяет грубый случайный доступ.

Отрывок из страницы своего руководства:

dictzip сжимает файлы с помощью алгоритма gzip (1) (LZ77) таким образом, полностью совместим с форматом файла gzip. Расширение gzip формат файла (дополнительное поле, описанное в разделе 2.3.1.1 RFC 1952) позволяет получить дополнительные данные для хранения в заголовке сжатого файла. Такие программы, как gzip и zcat будет игнорировать эти дополнительные данные. Однако [dictzcat -start] будет использовать этих данных для выполнения псевдослучайного доступа к файлу.

У меня есть пакет dictzip в Ubuntu. Или его исходный код находится в dictd - *. Tar.gz. Его лицензией является GPL. Вы можете изучить его.

Обновление:

Я улучшил dictzip, чтобы не иметь ограничения на размер файла. Моя реализация находится под лицензией MIT.

Ответ 3

.xz формат файла (который использует сжатие LZMA), похоже, поддерживает это:

Чтение с произвольным доступом. Данные можно разделить на блоки с независимым сжатием. Каждый .xz файл содержит индекс блоков, что делает возможным ограниченное чтение с произвольным доступом, когда размер блока достаточно мал.

Этого должно быть достаточно для вашей цели. Недостатком является то, что API liblzma (для взаимодействия с этими контейнерами) не выглядит настолько документированным, поэтому может потребоваться некоторое усилие, чтобы выяснить, как произвольно обращаться к блокам.

Ответ 5

bgzip может сжимать файлы в варианте gzip, который индексируется (и может быть распакован на gzip). Это используется в некоторых приложениях биоинформатики вместе с индексом tabix.

Смотрите здесь объяснения: http://blastedbio.blogspot.fr/2011/11/bgzf-blocked-bigger-better-gzip.html, и здесь: http://www.htslib.org/doc/tabix.html.

Я не знаю, насколько он адаптируется к другим приложениям.

Ответ 6

Я не уверен, что это будет практично в вашей конкретной ситуации, но не могли бы вы просто gzip каждый большой файл в более мелкие файлы, скажем, по 10 МБ каждый? В итоге у вас будет множество файлов: file0.gz, file1.gz, file2.gz и т.д. Основываясь на заданном смещении в оригинале большого размера, вы можете искать в файле с именем "file" + (offset / 10485760) + ".gz". Смещение в несжатом архиве будет offset % 10485760.

Ответ 7

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

Вы можете посмотреть на "Сжатие: ключ для поисковых систем следующего поколения" Нивио Зивиани, Эдлен Сильва де Мура, Гонсало Наварро и Рикардо Баэза-Йейтс в Компьютерный журнал, ноябрь 2000 г. http://doi.ieeecomputersociety.org/10.1109/2.881693

Их декомпрессор принимает 1, 2 или 3 целых байта сжатых данных и распаковывает (используя список слов) в целое слово. Можно напрямую искать сжатый текст для слов или фраз, который оказывается еще быстрее, чем поиск несжатого текста.

Их декомпрессор позволяет указывать любое слово в тексте с помощью обычного (байтового) указателя и сразу же запускать распаковку с этой точки.

Вы можете дать каждому слову уникальный 2-байтовый код, так как у вас, вероятно, есть меньше 65 000 уникальных слов в тексте. (В Библии KJV почти 13 000 уникальных слов). Даже если имеется более 65 000 слов, довольно просто назначить первые 256 двухбайтовых кодовых слов "слова" для всех возможных байтов, поэтому вы можете изложить слова, которые не входят в лексику из 65 000 или около того "наиболее часто встречающихся слова и фразы". (Сжатие, полученное путем упаковки частых слов и фраз в два байта обычно стоит "разрастание" изредка изложения слова, используя два байта на букву). Существует множество способов выбрать лексикон "частых слов и фраз", который даст адекватное сжатие. Например, вы можете настроить компрессор LZW на сброс "фраз", который он использует несколько раз, в файл лексикона, по одной строке на фразу и запускать его по всем вашим данным. Или вы можете произвольно расколоть несжатые данные на 5 байт-фраз в файле лексикона, по одной строке на фразу. Или вы можете нарезать свои несжатые данные в настоящие английские слова и поместить каждое слово, включая пробел в начале слова, в файл лексикона. Затем используйте "sort -unique" для устранения повторяющихся слов в этом файле лексикона. (Собирает идеальный "оптимальный" словарный словарь для лексики, который все еще считается NP-hard?)

Сохраните лексику в начале вашего огромного сжатого файла, отложите ее до некоторого удобного BLOCKSIZE, а затем сохраните сжатый текст - серию из двух байтовых слов - оттуда до конца файла. Предположительно, поисковик прочитает этот лексикон один раз и сохранит его в некотором быстром декодировании в ОЗУ во время декомпрессии, чтобы ускорить декомпрессию "двухбайтового кода" до "фразы переменной длины". Мой первый проект начнется с простой строки на список фразы, но позже вы можете переключиться на сохранение лексикона в более сжатой форме с использованием какого-либо инкрементного кодирования или zlib.

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

Ответ 8

Два возможных решения:

  • Позвольте ОС справиться с сжатием, создать и смонтировать сжатую файловую систему (SquashFS, clicfs, cloop, cramfs, e2compr или что-то еще), содержащее все ваши текстовые файлы и ничего не делать с сжатием в вашей прикладной программе.

  • Используйте clicfs непосредственно для каждого текстового файла (один clicfs для текстового файла) вместо сжатия образа файловой системы. Подумайте, что "mkclicfs mytextfile mycompressedfile" является "gzip <mytextfile> mycompressedfile" и "clicfs mycompressedfile directory" как способ получения случайного доступа к данным через файл "directory/mytextfile".

Ответ 9

Я не знаю, было ли упомянуто еще, но проект Киви сделал большую работу в этом отношении. Благодаря своей программе Kiwix они предлагают произвольный доступ к архивным файлам ZIM. Хорошее сжатие тоже. Проект возник, когда возникла потребность в автономных копиях Википедии (которая достигла 100 ГБ в несжатой форме, причем все носители включены). Они успешно взяли 25-гигабайтный файл (однопользовательский вариант википедии без большинства носителей) и сжали его до ничтожного 8-гигабайтного архива zim. И через программу Kiwix вы можете вызвать любую страницу Википедии со всеми связанными данными быстрее, чем вы можете заниматься серфингом в сети.

Несмотря на то, что программа Kiwix - это технология, основанная на структуре базы данных wikipedia, она доказывает, что вы можете иметь превосходные коэффициенты сжатия и произвольный доступ одновременно.

Ответ 10

Это очень старый вопрос, но он выглядит как zindex может стать хорошим решением (хотя у меня нет большого опыта работы с она)

Ответ 11

razip поддерживает произвольный доступ с лучшей производительностью, чем gzip/bzip2, который необходимо настроить для этой поддержки - сокращение сжатия за счет "нормально" произвольного доступа:

http://sourceforge.net/projects/razip/

Ответ 12

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

Данные пер-хромосомы преобразуются для удаления избыточности в геномных координатах, а преобразованные данные сжимаются либо с помощью алгоритмов bzip2, либо gzip. Смещения, метаданные и сжатые геномные данные объединяются в один файл.

Исходный код доступен на нашем GitHub сайте. Мы скомпилировали его под Linux и Mac OS X.

В вашем случае вы можете сохранить смещения (10 МБ или что-то еще) в заголовке в формате пользовательского архива. Вы анализируете заголовок, извлекаете смещения и инкрементно fseek через файл с помощью current_offset_sum + header_size.

Ответ 13

К формату gzip можно получить произвольный доступ при условии, что ранее был создан индекс, что продемонстрировано в исходном коде zlib zran.c.

Я разработал инструмент командной строки для zlib zran.c, который создает индексы для файлов gzip: https://github.com/circulosmeos/gztool

Он может даже создать индекс для все еще растущего файла gzip (например, журнала, созданного rsyslog непосредственно в формате gzip), тем самым уменьшая на практике время создания индекса. Смотрите -S (Supervise).