Различное поведение для процесса распаковки файлов gz - PullRequest
0 голосов
/ 03 октября 2018

У меня есть несколько файлов gz, на которых распаковка не работает должным образом.Я выбрал один из них, этот файл находится в локальной папке и поступил из внешнего источника.Я не знаю процесс сжатия.

Я создал скрипт на python, чтобы проиллюстрировать ситуацию.Чтобы получить эталонный файл для тестирования, я распаковал файл gz и снова сжал его (используя gzip в Ubuntu), чтобы создать тот же файл gz на моем компьютере.Эти два файла имеют различное поведение:

    import gzip
    import zlib
    import hashlib

    def md5(content):
        m = hashlib.md5()
        m.update(content)
        return m.hexdigest()

    def decompress_gzip_size(file_name):
        with gzip.open(file_name, 'rb') as f_out:
            f_content = f_out.read()
            print(len(f_content), file_name)
            print (md5(f_content), file_name)

    def decompress_open_gzip_size(file_name):
        with open(file_name, 'rb') as f_out:
            f_content = f_out.read()
            unzip_content = gzip.decompress(f_content)
            print(len(unzip_content), file_name)
            print (md5(unzip_content), file_name)

    def decompress_zlib_size(file_name):
        with open(file_name, 'rb') as f_out:
            f_content = f_out.read()
            unzip_content = zlib.decompress(f_content, 32)
            print(len(unzip_content), file_name)
            print (md5(unzip_content), file_name)

    def decompress_zlib_obj(file_name):
        decompress_obj = zlib.decompressobj(32)
        with open(file_name, 'rb') as f_out:
            f_content = f_out.read()
            unzip_content = decompress_obj.decompress(f_content)
            print(len(unzip_content), file_name)
            print(len(decompress_obj.unused_data), 'Unused data')
            print (md5(unzip_content), file_name)

    external_file = 'external_source_compress.gz'
    my_file = 'my-compress-file.gz'

    print("decompress_gzip_size")
    decompress_gzip_size(my_file)
    decompress_gzip_size(external_file)
    print("*" * 60)

    print("decompress_open_gzip_size")
    decompress_open_gzip_size(my_file)
    decompress_open_gzip_size(external_file)
    print("*" * 60)

    print("decompress_zlib_size")
    decompress_zlib_size(my_file)
    decompress_zlib_size(external_file)
    print("*" * 60)

    print("decompress_zlib_obj")
    decompress_zlib_obj(my_file)
    decompress_zlib_obj(external_file)
    print("*" * 60)

Вывод выполнения:

    decompress_gzip_size
    167019534 my-compress-file.gz
    a4dd17dd28b89f0b2c300b607cd1a8ba my-compress-file.gz
    167019534 external_source_compress.gz
    a4dd17dd28b89f0b2c300b607cd1a8ba external_source_compress.gz
    ************************************************************
    decompress_open_gzip_size
    167019534 my-compress-file.gz
    a4dd17dd28b89f0b2c300b607cd1a8ba my-compress-file.gz
    167019534 external_source_compress.gz
    a4dd17dd28b89f0b2c300b607cd1a8ba external_source_compress.gz
    ************************************************************
    decompress_zlib_size
    167019534 my-compress-file.gz
    a4dd17dd28b89f0b2c300b607cd1a8ba my-compress-file.gz
    33408639 external_source_compress.gz
    4f51ccc64a7baab5ee5e2ce31e816409 external_source_compress.gz
    ### SIZES AND MD5 DO NOT MATCH ###
    ************************************************************
    decompress_zlib_obj
    167019534 my-compress-file.gz
    0 Unused data
    a4dd17dd28b89f0b2c300b607cd1a8ba my-compress-file.gz
    33408639 external_source_compress.gz
    46765202 Unused data
    4f51ccc64a7baab5ee5e2ce31e816409 external_source_compress.gz
    ### THERE IS SOME UNUSED DATA IN THE ORIGINAL FILE ###
    ************************************************************

ПРИМЕЧАНИЕ: декомпрессия zlib завершится неудачно, если параметры размера окна отличаются от 32.

Без установки размера окна это происходит:

    Traceback (most recent call last):
      File "decompress_python.py", line 53, in <module>
        decompress_zlib_size(my_file)
      File "decompress_python.py", line 26, in decompress_zlib_size
        unzip_content = zlib.decompress(f_content)
    zlib.error: Error -3 while decompressing data: incorrect header check

Как это видно.Без размера 32 окна скрипт завершается сбоем, но с размером окна 32 он завершается, но количество прочитанных байтов является лишь частью реального объема данных.

Файл имеет только один элемент внутри:

    gzip -l external_source_compress.gz
             compressed        uncompressed  ratio uncompressed_name
               58609586            33410520 -75.4% external_source_compress

Может ли кто-нибудь помочь мне понять, что здесь происходит?Я действительно потерян.Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 04 октября 2018

Ответ Флориана почти наверняка состоит в том, что происходит: файл gzip, который вы только частично распаковываете, должен иметь несколько членов.Чтобы распаковать следующий элемент, вы можете просто получить unused_data от объекта decompressobj и запустить другую декомпрессию.Повторяйте до тех пор, пока не будут использованы все входные данные.

В этом ответе показан пример обработки файла gzip с несколькими членами в python.

Звучит так, как и должно бытьдля параметра wbits используется значение 31, а не 32. 31 ожидает упаковщик gzip, а не упаковщик zlib.Если вы не укажете wbits, декомпрессор будет ожидать оболочки zlib, поэтому он не работает с вашими потоками gzip.

0 голосов
/ 03 октября 2018

gzip-потоки могут состоять из нескольких сжатых независимо друг от друга элементов, которые затем просто объединяются.Ожидается, что декомпрессор в стиле gzip прозрачно считывает все независимо сжатые части, создавая один выходной поток (в основном игнорируя внутренние индикаторы окончания потока).

В документации zlib.compressobj не говоритсяэто, но он остановится на первом обнаруженном zlib внутреннем конце условия потока.Остальные данные могут быть обработаны независимо.В некоторых приложениях (но не в вашем) это могут быть данные, сжатые не zlib.

...