Согласно RFC 1950 , разница между «OK» 0x789C и «плохим» 0x78DA находится в битовом поле FLEVEL:
FLEVEL (Compression level)
These flags are available for use by specific compression
methods. The "deflate" method (CM = 8) sets these flags as
follows:
0 - compressor used fastest algorithm
1 - compressor used fast algorithm
2 - compressor used default algorithm
3 - compressor used maximum compression, slowest algorithm
The information in FLEVEL is not needed for decompression; it
is there to indicate if recompression might be worthwhile.
«ОК» использует 2, «плохо» использует 3. Так что разница сама по себе не является проблемой.
Чтобы продолжить, вы можете подумать о том, чтобы предоставить следующую информацию для каждого из сжатий и (попыток) распаковки: какая платформа, какая версия Python, какая версия библиотеки zlib, какой код использовался для вызова zlib модуль. Также предоставьте полный возврат и сообщение об ошибке от неудачных попыток распаковки. Вы пытались распаковать сбойные файлы любым другим программным обеспечением для чтения zlib? С какими результатами? Пожалуйста, уточните, с чем вы должны работать: «Есть ли у меня шланг?» значит, у вас нет доступа к исходным данным? Как он попал из потока в файл? Какая у вас гарантия, что данные не были искажены при передаче?
ОБНОВЛЕНИЕ Некоторые наблюдения, основанные на частичных разъяснениях, опубликованные в вашем ответе:
Вы используете Windows. Windows различает двоичный режим и текстовый режим при чтении и записи файлов. При чтении в текстовом режиме Python 2.x изменяет «\ r \ n» на «\ n» и изменяет «\ n» на «\ r \ n» при записи. Это не очень хорошая идея при работе с нетекстовыми данными. Хуже того, при чтении в текстовом режиме '\ x1a', он же Ctrl-Z, рассматривается как конец файла.
Чтобы сжать файл:
# imports and other superstructure left as a exercise
str_object1 = open('my_log_file', 'rb').read()
str_object2 = zlib.compress(str_object1, 9)
f = open('compressed_file', 'wb')
f.write(str_object2)
f.close()
Чтобы распаковать файл:
str_object1 = open('compressed_file', 'rb').read()
str_object2 = zlib.decompress(str_object1)
f = open('my_recovered_log_file', 'wb')
f.write(str_object2)
f.close()
В сторону: лучше использовать модуль gzip, который избавляет вас от необходимости думать о таких проблемах, как текстовый режим, за счет нескольких байтов для дополнительной информации заголовка.
Если вы использовали 'rb' и 'wb' в своем коде сжатия, но не в своем коде декомпрессии [маловероятно?], Вы не задумались, вам просто нужно выделить вышеприведенный код декомпрессии и пойти на это.
Обратите внимание на использование «май», «должен» и т. Д. В следующих непроверенных идеях.
Если вы не использовали 'rb' и 'wb' в своем коде сжатия, вероятность того, что вы использовали шланг, довольно высока.
Если в исходном файле были какие-либо экземпляры '\ x1a', любые данные после первого такого файла теряются, но в этом случае они не должны давать сбой при декомпрессии (IOW, этот сценарий не соответствует вашим симптомам) .
Если Ctrl-Z был сгенерирован самой zlib, это должно вызвать ранний EOF при попытке распаковки, что, конечно, должно вызвать исключение. В этом случае вы можете осторожно повернуть процесс, прочитав сжатый файл в двоичном режиме, а затем заменить \ r \ n на \ n '[т.е. имитировать текстовый режим без трюка Ctrl-Z -> EOF]. Распакуйте результат. Редактировать Записать результат в режиме ТЕКСТ. Конец редактирования
ОБНОВЛЕНИЕ 2 Я могу воспроизвести ваши симптомы - ЛЮБОЙ уровень от 1 до 9 - с помощью следующего сценария:
import zlib, sys
fn = sys.argv[1]
level = int(sys.argv[2])
s1 = open(fn).read() # TEXT mode
s2 = zlib.compress(s1, level)
f = open(fn + '-ct', 'w') # TEXT mode
f.write(s2)
f.close()
# try to decompress in text mode
s1 = open(fn + '-ct').read() # TEXT mode
s2 = zlib.decompress(s1) # error -5
f = open(fn + '-dtt', 'w')
f.write(s2)
f.close()
Примечание: вам понадобится использовать достаточно большой текстовый файл (я использовал исходный файл размером 80 КБ), чтобы в результате распаковки содержалось '\ x1a'.
Я могу восстановить с помощью этого сценария:
import zlib, sys
fn = sys.argv[1]
# (1) reverse the text-mode write
# can't use text-mode read as it will stop at Ctrl-Z
s1 = open(fn, 'rb').read() # BINARY mode
s1 = s1.replace('\r\n', '\n')
# (2) reverse the compression
s2 = zlib.decompress(s1)
# (3) reverse the text mode read
f = open(fn + '-fixed', 'w') # TEXT mode
f.write(s2)
f.close()
ПРИМЕЧАНИЕ. Если в исходном файле есть байт '\ x1a' aka Ctrl-Z, а файл читается в текстовом режиме, этот байт и все последующие байты НЕ будут включены в сжатый файл, и, таким образом, НЕ может быть восстановлено. Для текстового файла (например, исходного кода) это совсем не потеря. Для бинарного файла вы, скорее всего, используете.
Обновление 3 [после позднего обнаружения, что в проблеме задействован уровень шифрования / дешифрования]:
Сообщение «Ошибка -5» указывает на то, что данные, которые вы пытаетесь распаковать, были искажены с момента сжатия. Если это не вызвано использованием текстового режима для файлов, подозрение (?) Очевидно падает на ваши расшифровщики и упаковщики шифрования. Если вам нужна помощь, вам нужно раскрыть источник этих упаковщиков. На самом деле, вы должны попытаться сделать (как я сделал) небольшой скрипт, который воспроизводит проблему на нескольких входных файлах. Во-вторых (как я сделал) посмотреть, можете ли вы отменить процесс при каких условиях. Если вам нужна помощь со вторым этапом, вам нужно обнародовать сценарий воспроизведения проблемы.