解压缩.gz文件并将其存储在.tar.gz档案中

莫文

我有以下问题:我正在编写一个函数,该函数查找一堆.gz文件,将其解压缩,并将各个未压缩的文件存储在更大的.tar.gz档案中。到目前为止,我设法用以下代码实现了它,但是手动计算未压缩的文件大小并设置TarInfo大小似乎有点黑,我想知道是否有针对我问题的更惯用的解决方案:

import gzip
import os
import pathlib
import tarfile

def gather_compressed_files(input_dir: pathlib.Path, output_file: str):
    with tarfile.open(output_file, 'w:gz') as tar:
        for input_file in input_dir.glob('*.gz'):
            with gzip.open(input_file) as fd:
                tar_info = tarfile.TarInfo(input_file.stem)
                tar_info.size = fd.seek(0, os.SEEK_END)
                fd.seek(0, os.SEEK_SET)
                tar.addfile(tar_info, fd)

我尝试TarInfo通过以下方式创建对象,而不是手动创建它:

tar_info = tar.gettarinfo(arcname=input_file.stem, fileobj=fd)

但是,此函数检索.gz我们打开的原始文件的路径fd以计算其大小,因此仅提供tar_info.size对应于压缩.gz数据而不是未压缩数据的参数,这不是我想要的。完全不设置tar_fino.size参数也不起作用,因为addfile在传递文件描述符时使用了上述大小。

有没有更好,更惯用的方式来实现这一目标,还是我坚持目前的解决方案?

暗影游侠

您的方法是避免将文件完全解压缩到磁盘或RAM的唯一方法。毕竟,您需要提前知道要添加到tar文件中的大小,而gzip文件并不真正知道它们自己的解压缩大小。ISIZE报头字段理论上提供解压缩的大小,但该字段被定义早在32位天,所以它实际上是尺寸模2**32; 最初4 GB的文件和0B的文件的文件大小相同ISIZE无论如何,Python不会公开ISIZE,所以即使它有用,也没有内置的方法可以做到这一点(您总是可以手动解析,但这并不完全是干净的或惯用的)。

如果要避免两次解压缩文件(一次seek转发,一次将其实际添加到tar文件中),以将其解压缩到磁盘为代价,则可以使用atempfile.TemporaryFile来避免两次解压缩(而无需存储原始文件)在内存中),并稍作调整:

import shutil
import tempfile

def gather_compressed_files(input_dir: pathlib.Path, output_file: str):
    with tarfile.open(output_file, 'w:gz') as tar:
        for input_file in input_dir.glob('*.gz'):
            with tempfile.TemporaryFile() as tf:
                # Could combine both in one with, but this way we close the gzip
                # file ASAP
                with gzip.open(input_file) as fd:
                    shutil.copyfileobj(fd, tf)
                tar_info = tarfile.TarInfo(input_file.stem)
                tar_info.size = tf.tell()
                tf.seek(0)
                tar.addfile(tar_info, tf)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章