Я пишу программу на C ++, на платформе Windows. Я хотел бы сжать некоторое хранение данных в char[]
массив, и вывести его в файл, а позже я буду загружать файл на сервер Unix, и я хочу, чтобы его можно было распаковать gzip -d
,
После долгих исследований я выбираю Mini-Z. Также я нашел формат файла gzip Вот.
Вот фрагмент кода создания файла gzip: (извините, я не поместил определение некоторых переменных; они определены где-то еще)
unsigned long zsize;
zpkg[0] = 0x1F;
zpkg[1] = 0x8B;
zpkg[2] = 8;
zpkg[3] = 0;
zpkg[4] = 0;
zpkg[5] = 0;
zpkg[6] = 0;
zpkg[7] = 0;
zpkg[8] = 0;
zpkg[9] = 0xFF;
compress2(zpkg + 10, &zsize, pkg, pkgSize, MZ_DEFAULT_LEVEL);
int footerStart = (int)zsize + 10;
mz_ulong crc = mz_crc32(MZ_CRC32_INIT, zpkg + 10, zsize);
zpkg[footerStart] = crc & 0xFF;
zpkg[footerStart + 1] = (crc >> 8) & 0xFF;
zpkg[footerStart + 2] = (crc >> 16) & 0xFF;
zpkg[footerStart + 3] = (crc >> 24) & 0xFF;
zpkg[footerStart + 4] = pkgSize & 0xFF;
zpkg[footerStart + 5] = (pkgSize >> 8) & 0xFF;
zpkg[footerStart + 6] = (pkgSize >> 16) & 0xFF;
zpkg[footerStart + 7] = (pkgSize >> 24) & 0xFF;
А потом просто выведите zpkg
массив в файл. Однако это не работает; когда я распаковываю его с помощью gzip, сообщение об ошибке выглядит так:
gzip: data stream error
gzip: test.gz: uncompress failed
Кто-нибудь может указать мне, что я делаю не так?
Спасибо Марку Адлеру и Майклу, я разобрался с рабочим решением.
Во-первых, как отметил Марк, я должен заставить miniz возвращать поток необработанных данных. Это можно сделать, передав -MZ_DEFAULT_WINDOW_BITS
(обратите внимание на знак минус), чтобы mz_deflateInit2()
в качестве четвертого параметра. Глядя на мини-исходный код, compress2()
функция в конце концов вызывает mz_deflateInit2()
с MZ_DEFAULT_WINDOW_BITS
, что означает добавление zlib header и footer. Таким образом, самое простое решение — добавить знак минус, чтобы я все еще мог использовать compress2()
функция. (это работает для меня, потому что я вызываю эту функцию только в одном месте)
Во-вторых, как указал Майкл, код CRC должен рассчитываться на несжатых данных. Поэтому я исправляю это так:
mz_ulong crc = mz_crc32(MZ_CRC32_INIT, pkg, pkgSize);
После внесения двух изменений выше, gzip -d
больше не жалуется.
compress2()
создает поток zlib, который сжимает сжатые данные с заголовком и трейлером zlib. Для того, что вы делаете, вы хотите, чтобы только сжатый поток с сырым дефлятом вставлялся в ваш сгенерированный вручную заголовок gzip и трейлер.
Вы можете: а) отбросить первые два и последние четыре байта выходных данных compress2()
раздеть заголовок и трейлер zlib, б) использовать deflateInit2()
, deflate()
, а также deflateEnd()
вместо compress2()
и выберите необработанный формат deflate, или c) используйте те же функции и вместо этого выберите формат gzip и избавьтесь от созданного вручную заголовка gzip и трейлера, так как deflate()
сделаю это для вас.
Я рекомендую с).