Как определить, сжат ли файл gzip? - PullRequest
21 голосов
/ 13 сентября 2010

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

Существует ли кроссплатформенный способ, используемый из Python для определения, сжат ли файл gzip или нет?

Является ли следующий надежным или обычный текстовый файл "случайно" может выглядеть как gzip, чтобы я мог получить ложные срабатывания?

Ответы [ 5 ]

36 голосов
/ 13 сентября 2010

Магическое число для сжатых gzip файлов равно 1f 8b.Хотя тестирование для этого не является надежным на 100%, маловероятно, что «обычные текстовые файлы» начинаются с этих двух байтов - в UTF-8 это даже не разрешено.* хоть.Даже gzip(1) сам не сможет распаковать файлы без него, если вы не --force отправите его.Вы, возможно, можете использовать это, но вам все равно придется иметь дело с возможным IOError (который вы должны делать в любом случае).

Одна проблема с вашим подходом состоит в том, что gzip.GzipFile() не вызовет исключениеесли вы кормите его несжатый файл.Только позже read() будет.Это означает, что вам, вероятно, придется реализовать некоторую логику вашей программы дважды.Некрасиво.

8 голосов
/ 02 ноября 2017

«Существует ли кроссплатформенный способ использования Python для определения, сжат ли файл gzip или нет?»

Принятый ответ дал мне 90% пути к довольно надежному решениюесли первые два байта равны 1f 8b), но не показывают, как на самом деле это сделать в Python.Вот один из возможных способов:

import binascii

def is_gz_file(filepath):
    with open(filepath, 'rb') as test_f:
        return binascii.hexlify(test_f.read(2)) == b'1f8b'
2 голосов
/ 23 июня 2013

Импорт модуля mimetypes . Он может автоматически угадать, какой у вас файл, и сжимается ли он.

т.е.

mimetypes.guess_type('blabla.txt.gz')

возвращается:

('text / plain', 'gzip')

1 голос
/ 17 июля 2018

gzip само поднимет OSError, если это не сжатый файл.

>>> with gzip.open('README.md', 'rb') as f:
...     f.read()
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/Users/dennis/.asdf/installs/python/3.6.6/lib/python3.6/gzip.py", line 276, in read
    return self._buffer.read(size)
  File "/Users/dennis/.asdf/installs/python/3.6.6/lib/python3.6/gzip.py", line 463, in read
    if not self._read_gzip_header():
  File "/Users/dennis/.asdf/installs/python/3.6.6/lib/python3.6/gzip.py", line 411, in _read_gzip_header
    raise OSError('Not a gzipped file (%r)' % magic)
OSError: Not a gzipped file (b'# ')

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

import pathlib

if '.gz' in pathlib.Path(filepath).suffixes:
   # some more inexpensive checks until confident we can attempt to decompress
   # ...
   try ...
     ...
   except OSError as e:
     ...
0 голосов
/ 03 февраля 2015

В Python3 не очень хорошо работает ...

import mimetypes
filename = "./datasets/test"

def file_type(filename):
    type = mimetypes.guess_type(filename)
    return type
print(file_type(filename))

возвращает (Нет, Нет) Но из команды unix "Файл"

: ~> наборы файлов /наборы тестовых данных / test: сжатые gzip данные, "iostat_collection", из Unix, последнее изменение: чт 29 января 07:09:34 2015

...