Как я могу работать с файлами Gzip, которые содержат дополнительные данные?

Я пишу сценарий, который будет работать с данными, поступающими из инструментов в виде потоков gzip. Примерно в 90% случаев модуль gzip работает отлично, но некоторые потоки вызывают ошибку IOError: не сжатый файл . Если заголовок gzip удален, а поток deflate направлен непосредственно в zlib , я вместо этого получаю Ошибка -3 при распаковке данных: неправильная проверка заголовка . Примерно через полдня, когда я бился головой об стену, я обнаружил, что потоки, в которых возникают проблемы, содержат кажущееся случайным количество дополнительных байтов (которые не являются частью данных gzip), добавленных в конец.

Мне кажется странным, что Python не может работать с этими файлами по двум причинам:

  1. И Gzip, и 7zip могут открывать эти "дополненные" файлы без проблем. (Gzip выдает сообщение декомпрессия ОК, завершающий мусор игнорируется , 7zip завершается успешно.)
  2. Документы Gzip и Python, похоже, указывают на то, что это должно работать: (выделено мной)

    Формат Gzip. txt :

    Должна быть возможность

    Мне кажется странным, что Python не может работать с этими файлами по двум причинам:

    1. И Gzip, и 7zip могут открывать эти "дополненные" файлы без проблем. (Gzip выдает сообщение , декомпрессия ОК, завершающий мусор игнорируется , 7zip завершается успешно.)
    2. Документы Gzip и Python, похоже, указывают на то, что это должно работать: (выделено мной)

      Формат Gzip. txt :

      Должна быть возможность

      Мне кажется странным, что Python не может работать с этими файлами по двум причинам:

      1. И Gzip, и 7zip могут открывать эти "дополненные" файлы без проблем. (Gzip выдает сообщение декомпрессия ОК, завершающий мусор игнорируется , 7zip завершается успешно.)
      2. Документы Gzip и Python, похоже, указывают на то, что это должно работать: (выделено мной)

        Формат Gzip. txt :

        Должна быть возможность detect the end of the compressed data with any compression method, regardless of the actual size of the compressed data. In particular, the decompressor must be able to detect and skip extra data appended to a valid compressed file on a record-oriented file system, or when the compressed data can only be read from a device in multiples of a определенный размер блока.

        Python gzip.GzipFile` :

        Вызов метода close () объекта GzipFile не закрывает fileobj , , поскольку вы, возможно, захотите добавить больше материала после сжатых данных . Это также позволяет передать объект StringIO , открытый для записи как fileobj , и получить полученный буфер памяти с помощью getvalue () объекта StringIO метод

        Python zlib.Decompress.unused_data :

        Строка, которая содержит любые байты после конца сжатых данных. То есть он остается "" до тех пор, пока не станет доступен последний байт, содержащий данные сжатия. Если оказалось, что вся строка содержит сжатые данные, это "" , пустая строка.

        Единственный способ определить, где заканчивается строка сжатых данных, - это распаковать ее. Это означает, что когда сжатые данные являются частью более крупного файла, вы можете найти его конец, только прочитав данные и введя их с последующей непустой строкой в ​​функцию decopress () объекта декомпрессии. ], пока атрибут unused_data не станет пустой строкой.

      Вот четыре подхода, которые я пробовал. (Эти примеры относятся к Python 3.1, но я тестировал 2.5 и 2.7 и имел ту же проблему.)

      # 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 ] кажется ошибкой в ​​модуле, мои zlib проблемы возникают сами по себе. ; -)

      Копаясь в gzip.py , я понял, что делаю неправильно - по умолчанию zlib.decompress et al. ожидайте потоки, обернутые zlib, а не только потоки deflate. Передав отрицательное значение для 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:])
      

12
задан Ben Blank 8 February 2011 в 17:35
поделиться