Как конкатрировать два или более файла/потока gzip

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

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

Несколько примечаний:

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

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

Редактирование очистки:

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

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

Только Opera отлично справляется с этой задачей.

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

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

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

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

Ответ 1

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

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

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

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

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

Ответ 2

В руководстве 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.

Ответ 3

Если tar их не может быть и речи (поскольку связанное cat решение для вас не подходит):

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

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

tar xf A_B.gz.tar

Ответ 4

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

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

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