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

Rya*_*ard 21 python compression gzip

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

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

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

try:
    gzip.GzipFile(filename, 'r')
    # compressed
    # ...
except:
    # not compressed
    # ...
Run Code Online (Sandbox Code Playgroud)

小智 36

gzip压缩文件的神奇数字1f 8b.尽管对此进行测试并非100%可靠,但"普通文本文件"从这两个字节开始的可能性极小 - 在UTF-8中甚至不合法.

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

您的方法的一个问题是,gzip.GzipFile()如果您将其提供给未压缩的文件,则不会引发异常.只有一个晚了read().这意味着,您可能需要两次实现一些程序逻辑.丑陋.


the*_*ods 9

"是否存在跨平台,可以从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'
Run Code Online (Sandbox Code Playgroud)

  • 为了降低误报率,您可以测试前三个字节是“1f 8b 08”。 (4认同)
  • 也可以在没有 binascii 的情况下完成: `test_f.read(2) == b'\x1f\x8b'` (3认同)

win*_*i2k 8

测试gzip 文件的幻数是唯一可靠的方法。但是,从 python3.7 开始,不再需要自己比较字节。gzip 模块将为您比较字节,如果不匹配则引发异常!

从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')
Run Code Online (Sandbox Code Playgroud)

从 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')
Run Code Online (Sandbox Code Playgroud)