Сжатие форматов с хорошей поддержкой произвольного доступа в архивах? - PullRequest
51 голосов
/ 10 января 2009

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

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

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

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

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

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

Ответы [ 12 ]

31 голосов
/ 24 октября 2010

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

Выдержка из справочной страницы:

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

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

Обновление:

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

18 голосов
/ 10 января 2009

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

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

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

9 голосов
/ 03 мая 2014

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

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

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

7 голосов
/ 17 декабря 2010

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

( Я ищу что-нибудь для 7zip )

4 голосов
/ 04 февраля 2016

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

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

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

3 голосов
/ 10 февраля 2012

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

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

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

3 голосов
/ 08 августа 2010

Поскольку сжатие без потерь работает лучше в некоторых областях, чем в других, если вы храните сжатые данные в блоках удобной длины 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-сложным?)

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

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

3 голосов
/ 10 января 2009

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

1 голос
/ 04 сентября 2015

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

1 голос
/ 08 апреля 2013

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

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

...