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

41 投票
6 回答
49026 浏览
提问于 2025-04-16 04:05

我有一个Python程序,它会读取文本文件作为输入。不过,有些文件可能是经过gzip压缩的。

有没有一种可以在不同操作系统上使用的方法,来判断一个文件是否是gzip压缩的呢?

下面这个方法可靠吗?会不会有普通的文本文件“意外”看起来像gzip文件,从而让我误判呢?

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

6 个回答

15

测试一个gzip文件的魔法数字是唯一可靠的方法。不过,从Python 3.7开始,你不需要自己去比较字节了。gzip模块会帮你自动比较字节,如果不匹配,它会抛出一个异常!

在Python 3.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')

在Python 3.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')
47

有没有一种可以在不同平台上使用的、能从Python判断一个文件是否是gzip压缩的方式呢?

这个被接受的答案解释了如何一般性地检测一个gzip压缩文件:测试文件的前两个字节是否是 1f 8b。不过,它没有展示如何在Python中实现这个方法。

这里有一种实现方式:

def is_gz_file(filepath):
    with open(filepath, 'rb') as test_f:
        return test_f.read(2) == b'\x1f\x8b'
46

gzip压缩文件的“魔法数字”是 1f 8b。虽然检查这个并不是百分之百可靠,但普通的文本文件开头不太可能是这两个字节——在UTF-8编码中,这甚至是不合法的。

通常,gzip压缩文件的后缀是 .gz。就连 gzip(1) 本身也不会解压没有这个后缀的文件,除非你强制它这样做(使用 --force)。虽然你可以这样做,但你仍然需要处理可能出现的IO错误(无论如何你都得处理这个)。

你这种方法的一个问题是, gzip.GzipFile() 如果你给它一个未压缩的文件,它不会抛出异常。只有在后面调用 read() 时才会抛出异常。这意味着你可能需要在程序中实现一些逻辑两次,这样就显得很麻烦。

撰写回答