2016-12-25 2 views
3

python의 gzip 패키지를 사용하여 gzip의 아카이브 (또는 이진 데이터)의 압축을 풀고 rezipping하여 GNU gzip 버전과 Python의 gzip 간의 구현 차이를 더 잘 이해하려고합니다. .GzipFile. 유스 케이스는 압축 된 파일의 내용을 검사하고 출력을 변경하지 않고 다시 압축하고 싶습니다.GNU Gzip과 Python Gzip 간의 구현 불일치

하나의 불일치 나는 두 개의 다른 gzip 버전으로 파일을 압축하면 출력이 동일하다는 것을 알았습니다. 그러나 gzip.GzipFile로 압축하면 출력이 변경됩니다. 예를 들어

... 여기

은 LZO-2.09.tar.gz는 GZIP의 한 버전으로 압축 된 나는 다른을 사용하여 다시 압축하고있다. (. 타임 스탬프는 제외)

joga:/tmp/gztest$ ls -l lzo* 
[email protected] 1 joga wheel 594855 Dec 25 14:31 lzo-2.09.tar.gz 
[email protected] 1 joga wheel 594855 Dec 25 14:38 lzo-2.09_copy.tar.gz 
joga:/tmp/gztest$ gunzip lzo-2.09_copy.tar.gz 
joga:/tmp/gztest$ cat lzo-2.09_copy.tar |gzip -9 >lzo-2.09_copy.tar.gz 
joga:/tmp/gztest$ ls -l lzo* 
[email protected] 1 joga wheel 594855 Dec 25 14:31 lzo-2.09.tar.gz 
-rw-r--r-- 1 joga wheel 594855 Dec 25 14:39 lzo-2.09_copy.tar.gz 

우리는 여기에 대응하는 파이썬 스크립트입니다 출력은 동일 참조 :

import gzip 
from StringIO import StringIO 

with gzip.open('lzo-2.09.tar.gz', 'rb') as fh: 
    lzo_bin = fh.read() 

gzip_io = StringIO() 
compressed_gzip = gzip.GzipFile(fileobj=gzip_io, mode='wb', compresslevel=9) 

with compressed_gzip as gzip_handle: 
    gzip_handle.write(lzo_bin) 

with open('lzo_py.tar.gz', 'wb') as fh: 
    fh.write(gzip_io.getvalue()) 

는 그리고 우리는 결과가 다른 참조 :

joga:/tmp/gztest$ ls -l lzo* 
[email protected] 1 joga wheel 594855 Dec 25 14:31 lzo-2.09.tar.gz 
-rw-r--r-- 1 joga wheel 594855 Dec 25 14:39 lzo-2.09_copy.tar.gz 
-rw-r--r-- 1 joga wheel 595135 Dec 25 14:43 lzo_py.tar.gz 

두 개의 다시 압축 된 파일의 처음 몇 바이트는 다음과 같습니다.

GNU Gzi P :

00000000 1F 8B 08 00 00 00 00 00 02 FF 54 B7 63 8C 26 4C D8 A6 DD B6 ..........T.c.&L.... 

파이썬을 GzipFile

00000000 1F 8B 08 00 00 00 00 00 02 FF EC 7D 7B 7B DB B6 F5 F0 EF DF ...........}{{...... 

는 그 gzip을/zlib을 같은 파일의 두 복사본이 다른 패키지 버전으로 압축 할 때, 동일한 결과를 얻을 것이라는 보장을하지 않습니다 이해합니다. 그러나 경험적으로, 나는 그것이 많은 경우에있는 경우를 관찰했다.

제 질문은 -이 불일치로 이어질 수있는 Python 구현과 다른 점은 무엇입니까? 필자는 압축 기술이나 구현에 대한 배경 지식이 없지만 소스 코드를 살펴본 결과 직접 찾지 못했습니다.

+0

은 가장 길거나 가장 빈번한 문자열을 검색하기 위해 2 개의 약간 다른 구현이어야합니다. gzip 명령의 다른 버전 간에는 변경되지 않습니다. 파이썬 3로 해봤습니까? (코드를 수정해야합니다) –

+2

@ Jean-FrançoisFabre 그들이 서로 다른 구현이라고 생각하는 이유는 무엇입니까? 둘 다 zlib을 사용해야합니다. (파이썬'gzip' 모듈은 순수한 파이썬 구현이 아니기 때문에 믿을 수 없을 정도로 느릴 것입니다.) – duskwuff

+0

괜찮습니다. 관심있어, 계속 게시 해. –

답변

2

파이썬은 gzip과 다른 압축 코드를 가진 zlib을 사용합니다. 이전 사람의 gzip 코드에서 파생 된 zlib 코드를 사용하여 동일한 사람이 작성했습니다. 결과는 일반적으로 다릅니다.

그러나 다른 압축기가 동일한 압축되지 않은 입력에서 동일한 출력을 생성 할 수 있다는 보장은 없으며 필요도 없습니다. 확실한 것은 모두 보증해야하며, 다시 압축 해제하면 원래의 압축되지 않은 입력이 정확하게 생성됩니다. 이것은 무손실의 정의입니다.

그러면 압축 된 데이터가 어떻게 달라질 수 있습니까? 너 왜 신경 쓰냐?

+0

'tarfile.open (mode = "w : gz", fileobj = fh)'를 통해 파이썬에서 gzipped 파일을 생성하는 또 다른 방법이 있습니다. 그것은 세 번째 다른 결과를 줄 수 있습니다. 또한 gzippy와 같은 일부 모듈이 있습니다. 그럴 가치가 있습니다. – Gribouillis

+0

Mark - 내 질문에 답해 주셔서 감사합니다. 나는이 문제를 "압축"이라고 생각하지는 않겠지 만. 나는 파일의 크기를 바꾸지 않고 파일을 약간 수정하는 것에 관심이있다. (예를 들어, ASCII 텍스트 블록에서 4 개의 문자가 있으므로 파일 엔트로피는 동일하게 유지되어야한다.) 나는 zstream 자체가 다를 것이라고 기대하지만, 전체 압축 비율 또는 압축 된 출력 블롭의 크기도 동일해야합니다. 그러나 이것이 항상 그런 것은 아닙니다. 이것의 원인이 무엇일까요? 구현의 버퍼 크기는? 검색 알고리즘의 차이점은 무엇입니까? – jogarock

+0

예를 보지 않고, 또는 "~"로 무엇을 의미하는지 모른다고 말할 수는 없습니다. 일반적으로 근거없는 기대가 충족되지 않는다는 사실은 완전히 근거없는 기대 때문입니다. –

관련 문제