Как объединить два или более GZIP-файлов / потоков - PullRequest
13 голосов
/ 17 июля 2009

Я хочу объединить два или более потоков GZIP без их повторного сжатия.

Я имею в виду, что у меня A сжато до A.gz и B до B.gz, я хочу сжать их до одного gzip (A + B) .gz без повторного сжатия, используя C или C ++.

Несколько заметок:

  • Даже если вы можете просто объединить два файла, и gunzip будет знать, как с ними обращаться, большинство программ не смогут работать с двумя кусками.
  • Однажды я видел пример кода, который делает это просто путем распаковки файлов, а затем манипулируя оригиналом, и это значительно быстрее, чем обычное повторное сжатие, но все еще требует O (n) -процессорной работы.
  • К сожалению, я не могу найти этот пример, который я нашел однажды (конкатенация с использованием только декомпрессии), если кто-то может указать на это, я был бы очень рад.

Примечание: он не является дубликатом этого , поскольку предлагаемое решение не соответствует моим потребностям.

Редактирование разъяснений :

Я хочу объединить несколько сжатых HTML-фрагментов и отправить их в браузер одной страницей в соответствии с запросом: "Accept-Encoding: gzip", с ответом "Content-Encoding: gzip"

Если поток объединяется так просто, как cat a.gz b.gz >ab.gz, веб-движки Gecko (firefox) и KHTML получают только первую часть (a); В IE6 ничего не отображается, а в Google Chrome первая часть (а) отображается правильно, а вторая (б) - как мусор (вообще не распаковывается).

Только Опера справляется с этим хорошо.

Поэтому мне нужно создать один gzip поток из нескольких кусков и отправить их без повторного сжатия.

Обновление: Я обнаружил gzjoin.c в примерах zlib, он использует только декомпрессию. Проблема в том, что декомпрессия все еще медленнее их просто memcpy.

Это все же быстрее в 4 раза, чем самое быстрое сжатие gzip. Но этого недостаточно.

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

Ответы [ 4 ]

12 голосов
/ 17 июля 2009

Посмотрите на RFC1951 и RFC1952

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

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

Проблема в том, что у трейлера есть CRC32 несжатых данных, и я не уверен, легко ли это вычислить, когда вы знаете CRC деталей.

Редактировать: комментарии в файле gzjoin.c, который вы обнаружили, подразумевают, что, хотя можно вычислить CRC32 без распаковки данных, существуют другие вещи, которые требуют распаковки.

6 голосов
/ 28 июля 2009

В руководстве gzip говорится, что два файла gzip могут быть объединены при попытке.

http://www.gnu.org/software/gzip/manual/gzip.html#Advanced-usage

Похоже, что другие инструменты могут быть сломаны. Как видно из этого сообщения об ошибке. http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=97263

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

Как уже упоминали другие, вы можете выполнить операцию: http://www.gzip.org/zlib/rfc-gzip.html

И для этого требуется CRC-32 окончательного несжатого файла. Требуемый размер несжатого файла может быть легко вычислен путем добавления длины отдельных вложенных файлов.

В нижней части последней ссылки находится код для вычисления запущенного crc-32 с именем update_crc.

Расчет crc для несжатых файлов при каждом запуске процесса, вероятно, дешевле, чем сам алгоритм gzip.

2 голосов
/ 26 июля 2009

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

Обратите внимание, что (1) подход gzjoin.c, скорее всего, будет лучшим ответом на ваш вопрос, как указано (2) это сложная микрохирургия, выполненная одним из создателей gzip и, возможно, подвергается всестороннему стресс-тестированию.

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

2 голосов
/ 17 июля 2009

Если tar их не исключено (так как связанное cat решение не подходит для вас):

tar cf A_B.gz.tar A.gz B.gz

Затем, чтобы вернуть их:

tar xf A_B.gz.tar
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...