Расстегиваю часть А. файл 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.
Иамин