계측에서 나온 데이터를 gzip 스트림으로 사용할 수있는 스크립트를 작성 중입니다. 약 90 %의 경우에 gzip
모듈이 완벽하게 작동하지만 일부 스트림에서는 IOError: Not a gzipped file
을 생성합니다. gzip 헤더가 제거되고 수축 된 스트림이 zlib
으로 직접 입력되면 나는 대신 Error -3 while decompressing data: incorrect header check
을 얻습니다. 벽에 머리를 대고 약 반나절 만 지나면, 문제가있는 스트림에 마지막에 추가 된 여분의 바이트 (gzip 데이터의 일부가 아닌)가 겉보기에 무작위로 포함되어 있음을 발견했습니다.추가 데이터가 포함 된 Gzip 파일을 사용하려면 어떻게해야합니까?
그것은 파이썬은 두 가지 이유에서이 파일을 사용하여 작업 할 수없는 이상한 나를 친다 : Gzip으로하고 7zip과 모두 문제없이이 "패딩"파일을 열 수 있습니다
- . (. Gzip으로 메시지
decompression OK, trailing garbage ignored
가, 7zip과 조용히 성공 생산) 것은 모두 Gzip으로 파이썬 문서는이 일을해야 함을 표시하는 것 (강조 광산)
이그것은 가능해야한다 은 압축 된 데이터의 실제 크기에 관계없이 모든 압축 방법 으로 압축 된 데이터의 끝을 감지합니다. 특히 압축 해제를 감지하고 이동 를 첨부 된 추가 데이터를 유효한 압축 파일에 기록 지향 파일 시스템에, 또는 수 있어야 압축 데이터 만 의 배수 장치로부터 판독 될 때 특정 블록 크기.
GzipFile
객체의close()
메서드를 호출. 또한
StringIO
개체를 쓰기 위해 열어 fileobj으로 전달하고StringIO
개체의getvalue()
메서드를 사용하여 결과 메모리 버퍼를 검색 할 수 있습니다.Python's
:zlib.Decompress.unused_data
압축 된 데이터의 끝을지나 모든 바이트를 포함하는 문자열입니다. 즉, 압축 데이터가 포함 된 마지막 바이트가 사용 가능할 때까지이 값은
""
입니다. 전체 문자열이 압축 된 데이터를 포함하고있는 것으로 밝혀지면이 문자열은 빈 문자열""
입니다.압축 된 데이터 문자열이 실제로 끝나는 곳을 확인하는 유일한 방법은 실제로 압축을 풀는 것입니다. 즉, 압축 된 데이터가 큰 파일의 일부로 포함되어있는 경우 데이터를 읽은 다음 비어 있지 않은 문자열을 뒤 따르고 메서드로 끝나는 부분을 찾을 수 있으며
unused_data
특성이 더 이상 존재하지 않을 때까지 빈 문자열여기
# approach 1 - gzip.open
with gzip.open(filename) as datafile:
data = datafile.read()
# approach 2 - gzip.GzipFile
with open(filename, "rb") as gzipfile:
with gzip.GzipFile(fileobj=gzipfile) as datafile:
data = datafile.read()
# approach 3 - zlib.decompress
with open(filename, "rb") as gzipfile:
data = zlib.decompress(gzipfile.read()[10:])
# approach 4 - zlib.decompressobj
with open(filename, "rb") as gzipfile:
decompressor = zlib.decompressobj()
data = decompressor.decompress(gzipfile.read()[10:])
잘못된 것이 있습니까? gzip
에 문제가 모듈에서 버그가 수 있도록 보인다 동안
UPDATE는
좋아, 내 zlib
문제가 자초. ;-)
gzip.py
을 파고 들자 내가 잘못하고있는 것을 깨달았습니다. 기본적으로 zlib.decompress
외. 벌거 벗은 스트림이 아닌 zlib-wrapped 스트림을 기대하십시오. wbits
에 음수 값을 전달하면 zlib
에 zlib 헤더를 건너 뛰고 원시 스트림의 압축을 해제하도록 지정할 수 있습니다. 두 가지 모두 작동합니다.
# approach 5 - zlib.decompress with negative wbits
with open(filename, "rb") as gzipfile:
data = zlib.decompress(gzipfile.read()[10:], -zlib.MAX_WBITS)
# approach 6 - zlib.decompressobj with negative wbits
with open(filename, "rb") as gzipfile:
decompressor = zlib.decompressobj(-zlib.MAX_WBITS)
data = decompressor.decompress(gzipfile.read()[10:])
문제를 디버깅하는 동안 실제로 gzip'의 내부 '와 비트에 대한 청소 만 싶지만, 그것을 해결하기 위해 나에게 발생하지 않았다 거기서 문제가 발생하여 수정 된 모듈을 내 스크립트로 패키지화하십시오.지옥처럼 추악하지만, 여전히 최상의 선택 옵션이 될 수 있습니다. : -/ –
@Ben : 최소한의 비용은 들지 않는다. 하나의 파일. 네이티브 모듈로 인해 더 귀찮습니다. –
해결 방법 : 코드의 크기 또는 시간 제약 조건을 위반하지 않는다고 가정하면 오류를받은 후 한 번에 한 바이트 씩 읽을 수 있습니다. 'gzipped 파일이 아닙니다'매개 변수가있는 다른 IOError를 수신하면 목록의 각 바이트를 추가하여 데이터 끝에 도달했습니다. ''.join을 반환하고 –