如何判断文件是否被gzip压缩?

时间:2010-09-13 18:27:07

标签: python compression gzip

我有一个Python程序,它将把文本文件作为输入。但是,其中一些文件可能是gzip压缩的。

是否存在跨平台,可以从Python方式使用以确定文件是否压缩为gzip?

以下是可靠的还是一个普通的文本文件'偶然'看起来像gzip一样足以让我得到误报?

try:
    gzip.GzipFile(filename, 'r')
    # compressed
    # ...
except:
    # not compressed
    # ...

6 个答案:

答案 0 :(得分:36)

gzip压缩文件的magic number1f 8b。尽管对此进行测试不是100%可靠,但“普通文本文件”从这两个字节开始的可能性极小 - 在UTF-8中甚至不合法。

通常,gzip压缩文件的后缀为.gz。除非你gzip(1),否则即使--force本身也不会解压缩文件。您可以想象使用它,但您仍然需要处理可能的IOError(在任何情况下都必须这样做)。

您的方法存在的一个问题是,gzip.GzipFile()如果您向其提供未压缩文件,则不会引发异常。只有稍后的read()会。这意味着,您可能需要两次实现一些程序逻辑。难看。

答案 1 :(得分:7)

“是否存在跨平台,可以通过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 :(得分:2)

导入mimetypes模块。 它可以自动猜测您拥有哪种文件,以及它是否已压缩。

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

返回:

('text / plain','gzip')

答案 3 :(得分:2)

从python3.7开始,这有效

import gzip
with gzip.open(input_file, 'r') as fh:
    try:
        fh.read(1)
    except OSError:
        print('input_file is not a valid gzip file by OSError')

从python3.8开始,这也有效:

import gzip
with gzip.open(input_file, 'r') as fh:
    try:
        fh.read(1)
    except gzip.BadGzipFile:
        print('input_file is not a valid gzip file by BadGzipFile')

答案 4 :(得分:1)

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:
     ...

答案 5 :(得分:0)

在python3中看起来效果不好......

import mimetypes
filename = "./datasets/test"

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

返回(无,无) 但是从unix命令“File”

:〜&GT;文件数据集/测试 数据集/测试:gzip压缩数据,是“iostat_collection”,来自Unix,最后修改时间:2015年1月29日07:09:34