Расстегиваю часть А. файл gz с использованием python

Так вот в чем проблема. У меня есть образец.GZ файл, который примерно 60KB в размере. Я хочу распаковать первые 2000 байт этого файла. Я сталкиваюсь с ошибкой CRC check failed, я думаю, потому что поле CRC gzip появляется в конце файла, и для распаковки требуется весь файл gzipped. Есть ли способ обойти это? Меня не волнует проверка CRC. Даже если я не смогу распаковать из-за плохого CRC, это нормально. Есть ли способ обойти это и распаковать частично .gz файлы?

код у меня есть до сих пор

import gzip
import time
import StringIO

file = open('sample.gz', 'rb')
mybuf = MyBuffer(file)
mybuf = StringIO.StringIO(file.read(2000))
f = gzip.GzipFile(fileobj=mybuf)
data = f.read()
print data

обнаружена ошибка

File "gunzip.py", line 27, in ?
    data = f.read()
File "/usr/local/lib/python2.4/gzip.py", line 218, in read
  self._read(readsize)
File "/usr/local/lib/python2.4/gzip.py", line 273, in _read
  self._read_eof()
File "/usr/local/lib/python2.4/gzip.py", line 309, in _read_eof
  raise IOError, "CRC check failed"
IOError: CRC check failed

также есть ли способ использовать модуль zlib для этого и игнорировать заголовки gzip?

4 ответов


Мне кажется, что вам нужно заглянуть в Python zlib библиотека

формат GZIP полагается на zlib, но вводит концепцию сжатия на уровне файла вместе с проверкой CRC, и это, похоже, то, что вы не хотите/не нужно в данный момент.

см., например, эти фрагменты кода из теста Hellman

редактировать: код на сайте Doubh Hellman показывает только, как сжимать или распаковки с помощью zlib. Как указано выше, GZIP - это "zlib с конвертом", и вам нужно будет декодировать envellope перед тем, как перейти к zlib-сжатым данным per se. Вот больше информации, чтобы пойти об этом, это действительно не так сложно:

  • посмотреть RFC 1952 для получения подробной информации о формате gzip
  • этот формат начинается с заголовка 10 байт, за которым следуют необязательные, не сжатые элементы, такие как имя файла или комментарий, за которым следуют zlib-сжатые данные, а затем CRC-32 (точно "ADLER32" CRC).
  • С помощью модуль структуры Python, разбор заголовка должен быть относительно простым
  • последовательность zlib (или ее первые несколько тысяч байтов, так как это то, что вы хотите сделать) может быть распакована с помощью модуля zlib python, как показано в примерах выше
  • возможные проблемы для обработки: если есть более одного файл в архиве GZip, и если второй файл запускается внутри блока в несколько тысяч байт, мы хотим распаковать.

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


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

ключ состоит в том, чтобы обмануть gzip в пропуск проверки. The ответ от caesar0301 изменяет исходный код gzip, но это не чтобы зайти так далеко, достаточно простого исправления обезьяны. Я написал этот менеджер контекста, чтобы временно заменить gzip.GzipFile._read_eof пока я распаковываю частичный файл:

import contextlib

@contextlib.contextmanager
def patch_gzip_for_partial():
    """
    Context manager that replaces gzip.GzipFile._read_eof with a no-op.

    This is useful when decompressing partial files, something that won't
    work if GzipFile does it's checksum comparison.

    """
    _read_eof = gzip.GzipFile._read_eof
    gzip.GzipFile._read_eof = lambda *args, **kwargs: None
    yield
    gzip.GzipFile._read_eof = _read_eof

пример использования:

from cStringIO import StringIO

with patch_gzip_for_partial():
    decompressed = gzip.GzipFile(StringIO(compressed)).read()

Я не вижу никакой возможной причины, по которой вы хотели бы распаковать первые 2000 сжатых байтов. В зависимости от данных это может распаковываться на любое количество выходных байтов.

конечно, вы хотите распаковать файл и остановиться, когда вы распаковали столько файла, сколько вам нужно, что-то вроде:

f = gzip.GzipFile(fileobj=open('postcode-code.tar.gz', 'rb'))
data = f.read(4000)
print data

AFAIK, это не приведет к чтению всего файла. Он будет читать только столько, сколько необходимо, чтобы получить первые 4000 байт.


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

прочитав реализацию gzip.py Python, я нашел, что gzip.GzipFile имел аналогичные методы класса файлов и использовал модуль Python zip для обработки данных de / compressing. В то же время метод _read_eof() также присутствует для проверки CRC каждого файла.

но в некоторых ситуации, как поток обработки или .файл gz без правильного CRC (моя проблема), IOError ("ошибка проверки CRC") будет вызван _read_eof (). Поэтому я пытаюсь изменить модуль gzip, чтобы отключить проверку CRC, и, наконец, эта проблема исчезла.

def _read_eof(self):
    pass

https://github.com/caesar0301/PcapEx/blob/master/live-scripts/gzip_mod.py

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

Иамин