it-swarm.com.ru

Сжатие форматов с хорошей поддержкой произвольного доступа в архивах?

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

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

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

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

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

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

51
John Zwinck

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

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

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

18
jpalecek

Взгляните на 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.

31
Ivo Danihelka

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

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

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

9
AardvarkSoup

Существуют решения для обеспечения произвольного доступа к архивам gzip и bzip2:

( я ищу что-то для 7Zip )

7
hippietrail

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

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

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

4
bli

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

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

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

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

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

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

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

3
David Cary

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

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

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

3
Joachim Wagner

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

3
William Brendel

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

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

1
CogitoErgoCogitoSum

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

1
robochat

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

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

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

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

0
Alex Reynolds

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

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

0
Erik Aronesty