如何读取包含在gz文件中的文件名

e.a*_*rio 7 python compression gzip

我试过读一个gz文件:

with open(os.path.join(storage_path,file), "rb") as gzipfile:
        with gzip.GzipFile(fileobj=gzipfile) as datafile:
            data = datafile.read()
Run Code Online (Sandbox Code Playgroud)

它工作,但我需要文件名和我的gz文件中包含的每个文件的大小.此代码将包含文件的内容打印到存档中.

如何读取此gz文件中包含的文件名?

Mar*_*ers 6

Python gzip模块不提供对该信息的访问.

源代码跳过它而不存储它:

if flag & FNAME:
    # Read and discard a null-terminated string containing the filename
    while True:
        s = self.fileobj.read(1)
        if not s or s=='\000':
            break
Run Code Online (Sandbox Code Playgroud)

文件名组件是可选的,不保证存在(我认为命令行gzip -c解压缩选项.gz在这种情况下将使用原始文件名sans ).未压缩的文件大小不存储在标头中; 你可以在最后四个字节中找到它.

要自己从头文件中读取文件名,您需要重新创建文件头读取代码,并保留文件名字节.以下函数返回,加上解压缩的大小:

import struct
from gzip import FEXTRA, FNAME

def read_gzip_info(gzipfile):
    gf = gzipfile.fileobj
    pos = gf.tell()

    # Read archive size
    gf.seek(-4, 2)
    size = struct.unpack('<I', gf.read())[0]

    gf.seek(0)
    magic = gf.read(2)
    if magic != '\037\213':
        raise IOError('Not a gzipped file')

    method, flag, mtime = struct.unpack("<BBIxx", gf.read(8))

    if not flag & FNAME:
        # Not stored in the header, use the filename sans .gz
        gf.seek(pos)
        fname = gzipfile.name
        if fname.endswith('.gz'):
            fname = fname[:-3]
        return fname, size

    if flag & FEXTRA:
        # Read & discard the extra field, if present
        gf.read(struct.unpack("<H", gf.read(2)))

    # Read a null-terminated string containing the filename
    fname = []
    while True:
        s = gf.read(1)
        if not s or s=='\000':
            break
        fname.append(s)

    gf.seek(pos)
    return ''.join(fname), size
Run Code Online (Sandbox Code Playgroud)

将上述函数与已创建的gzip.GzipFile对象一起使用:

filename, size = read_gzip_info(gzipfileobj)
Run Code Online (Sandbox Code Playgroud)