سؤال

ملفات تنسيق gzip (تم إنشاؤها مع gzip البرنامج، على سبيل المثال) استخدم خوارزم ضغط "الانفديل"، وهو نفس خوارزم الضغط مثل ما zlib. الاستخدامات. ومع ذلك، عند استخدام ZLIB لتضخير ملف مضغوط Gzip، تقوم المكتبة بإرجاع Z_DATA_ERROR.

كيف يمكنني استخدام ZLIB لإلغاء ضغط ملف Gzip؟

هل كانت مفيدة؟

المحلول

لإلغاء ضغط ملف تنسيق Gzip مع ZLIB، اتصل inflateInit2 مع ال windowBits المعلمة كما 16+MAX_WBITS, ، مثله:

inflateInit2(&stream, 16+MAX_WBITS);

إذا لم تقم بذلك، فسوف يشتكي ZLIB من تنسيق دفق سيء. بشكل افتراضي، يقوم ZLIB بإنشاء تدفقات ذات رأس ZLIB، وعلى تضخيم لا يتعرف على رأس Gzip المختلف إلا إذا أخبرته بذلك. على الرغم من أن هذا موثق يبدأ في الإصدار 1.2.1 من zlib.h ملف الرأس، إنه ليس في دليل ZLIB. وبعد من ملف الرأس:

windowBits يمكن أن يكون أيضا أكبر من 15 للحصول على فك تشفير gzip الاختياري. إضافة 32 إلى windowBits لتمكين فك تشفير ZLIB و GZIP مع كشف الرأس التلقائي، أو أضف 16 لفك تشفير فقط تنسيق Gzip (سوف يعيد تنسيق ZLIB Z_DATA_ERROR). إذا تم فك تشفير دفق gzip، strm->adler هو CRC32 بدلا من Adler32.

نصائح أخرى

بيثون

zlib دعم المكتبة:

بيثون zlib الوحدة سوف تدعم هذه كذلك.

اختيار windowbits.

ولكن zlib يمكن إلغاء ضغط كل تلك التنسيقات:

  • إلى (de-) ضغط deflate التنسيق، واستخدام wbits = -zlib.MAX_WBITS
  • إلى (de-) ضغط zlib التنسيق، واستخدام wbits = zlib.MAX_WBITS
  • إلى (de-) ضغط gzip التنسيق، واستخدام wbits = zlib.MAX_WBITS | 16

انظر الوثائق في http://www.zlib.net/manual.html#advanced. (الجزء inflateInit2)

أمثلة

بيانات الاختبار:

>>> deflate_compress = zlib.compressobj(9, zlib.DEFLATED, -zlib.MAX_WBITS)
>>> zlib_compress = zlib.compressobj(9, zlib.DEFLATED, zlib.MAX_WBITS)
>>> gzip_compress = zlib.compressobj(9, zlib.DEFLATED, zlib.MAX_WBITS | 16)
>>> 
>>> text = '''test'''
>>> deflate_data = deflate_compress.compress(text) + deflate_compress.flush()
>>> zlib_data = zlib_compress.compress(text) + zlib_compress.flush()
>>> gzip_data = gzip_compress.compress(text) + gzip_compress.flush()
>>> 

اختبار واضح ل zlib:

>>> zlib.decompress(zlib_data)
'test'

اختبار ل deflate:

>>> zlib.decompress(deflate_data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
zlib.error: Error -3 while decompressing data: incorrect header check
>>> zlib.decompress(deflate_data, -zlib.MAX_WBITS)
'test'

اختبار ل gzip:

>>> zlib.decompress(gzip_data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
zlib.error: Error -3 while decompressing data: incorrect header check
>>> zlib.decompress(gzip_data, zlib.MAX_WBITS|16)
'test'

البيانات متوافقة أيضا مع gzip وحدة:

>>> import gzip
>>> import StringIO
>>> fio = StringIO.StringIO(gzip_data)
>>> f = gzip.GzipFile(fileobj=fio)
>>> f.read()
'test'
>>> f.close()

الكشف عن الرأس التلقائي (ZLIB أو GZIP)

إضافة 32 ل windowBits سوف يؤدي إلى اكتشاف رأس الرأس

>>> zlib.decompress(gzip_data, zlib.MAX_WBITS|32)
'test'
>>> zlib.decompress(zlib_data, zlib.MAX_WBITS|32)
'test'

استخدام gzip في حين أن

بالنسبة gzip البيانات مع رأس gzip يمكنك استخدامها gzip الوحدة النمطية مباشرة. لكن يرجى تذكر ذلك تحت غطاء محرك السيارة, gzip الاستخدامات zlib.

fh = gzip.open('abc.gz', 'rb')
cdata = fh.read()
fh.close()

هيكل ZLIB و Gzip مختلفة. يستخدم zlib RFC 1950. و gzip يستخدم RFC 1952.، لذلك لديهم رؤوس مختلفة ولكن البقية لها نفس الهيكل ويتبع RFC 1951..

node.js.

const { gunzip } = require('zlib');

const decompressGzip = compressedData =>
  new Promise((resolve, reject) => {
    gunzip(compressedData, (error, decompressedData) => {
      if (error) return reject(error);
      return resolve(decompressedData);
    });
  });

module.exports = { decompressGzip };

قمت بتثبيت zlib باستخدام الغزل

yarn add zlib
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top