zlib로 gzip 스트림의 압축을 풀려면 어떻게해야합니까?


108

gzip예를 들어 프로그램으로 만든 Gzip 형식 파일 은 zlib가 사용 하는 것과 동일한 압축 알고리즘 인 "deflate"압축 알고리즘을 사용합니다. 그러나 zlib를 사용하여 gzip 압축 파일을 부 풀릴 때 라이브러리는 Z_DATA_ERROR.

zlib를 사용하여 gzip 파일의 압축을 풀려면 어떻게해야합니까?

답변:


118

zlib를 사용하여 gzip 형식 파일의 압축을 풀려면 다음 inflateInit2과 같이 windowBits매개 변수를으로 호출 16+MAX_WBITS합니다.

inflateInit2(&stream, 16+MAX_WBITS);

이렇게하지 않으면 zlib는 잘못된 스트림 형식에 대해 불평합니다. 기본적으로 zlib는 zlib 헤더로 스트림을 생성하며 inflate에서는 사용자가 지정하지 않는 한 다른 gzip 헤더를 인식하지 못합니다. 이것은 zlib.h헤더 파일 의 버전 1.2.1부터 문서화되어 있지만 zlib 매뉴얼 에는 없습니다 . 헤더 파일에서 :

windowBits선택적인 gzip 디코딩의 경우 15보다 클 수도 있습니다. windowBits자동 헤더 감지로 zlib 및 gzip 디코딩을 활성화 하려면 에 32를 추가하고 gzip 형식 만 디코딩하려면 16을 추가하십시오 (zlib 형식은를 반환합니다 Z_DATA_ERROR). gzip 스트림이 디코딩되는 strm->adler경우 adler32 대신 crc32입니다.


35
파이썬에서 :zlib.decompress(data, 15 + 32)
Roman Starkov

3
감사합니다.이 게시물을 찾을 때까지 매우 실망 스러웠습니다.
Alex

와, 이건 2009 년의 질문입니다. 감사합니다 @Greg Hewgill
위안 소림 Maculelê 라이

gzip 스트림의 반복 압축 해제에 대한 몇 가지 지침을 제공 할 수 있습니다. 출력 스트림과 크기가 고정되고 압축 해제 된 전체 출력을 저장하기에 충분한 원샷 gzip 압축 해제에서. 이 값은 데이터 엔트로피에 따라 달라질 수있는 gzip 압축 해제 효과에 따라 다릅니다. 필요할 때 출력 버퍼에 더 많은 공간을 동적으로 할당하는 방법이 있습니까? 감사합니다
Zohar81

104

파이썬

zlib도서관 지원 :

파이썬 zlib모듈은 이것도 지원합니다.

windowBits 선택

그러나 zlib이러한 모든 형식의 압축을 풀 수 있습니다.

  • deflate형식 을 (해제) 압축 하려면wbits = -zlib.MAX_WBITS
  • zlib형식 을 (해제) 압축 하려면wbits = zlib.MAX_WBITS
  • 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하는 대신

대한 gzipGZIP 헤더 사용할 수와 데이터 gzip를 직접 모듈을; 하지만 후드 것을 기억하시기 바랍니다 , gzip용도 zlib.

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

3
이 금 조각이 정확히이 형식의 문서에없는 이유는 무엇입니까?
Ramon Moraes

이 답변 중 하나를 사용하여 cpython에 대한 풀 요청 / 패치를 보내 주시기 바랍니다.
dnozay

문자열에 대한 훌륭한 대답, 전체 파일을 메모리로 읽지 않고 스트림에 대해 이것을 수행하는 방법에 대한 아이디어가 있습니까?
Josh J

감사합니다. 귀하의 답변으로 내 소스 코드의 압축 해제 문제를 해결할 수 있습니다.
Bethlee

놀랍습니다, 이것은 금 덩어리입니다 .. 그러나 나는 이것이 '마법의 숫자'에 상응하는 것이라고 느낄 수밖에 없습니까? 문서에서 이것이 언급 된 곳은 어디입니까? 나는 봤지만, 충분히 확인하지 않았 음에 틀림 없다. 또한, 내가 완전히 따르지 않는 표기법. 무엇을 | 선택 사항인가요? 그 이유는 음극 DEFLATE이다 .. 일정한 MAX_WBITS이다 .. 🙁
m1nkeh

3

zlib와 gzip의 구조는 다릅니다. zlib는 RFC 1950 을 사용하고 gzip은 RFC 1952 를 사용하므로 헤더가 다르지만 나머지는 동일한 구조를 가지며 RFC 1951을 따릅니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.