首页 > 解决方案 > 是否可以从压缩文件中删除字符而不提取它?

问题描述

我有一个大约 200 MB 的压缩文件,格式为 tar.gz 文件。我知道我可以提取其中的 xml 文件。它包含几个小的和一个 5 GB 的 xml 文件。我正在尝试从 xml 文件中删除某些字符。

所以我非常基本的问题是:是否有可能在不提取压缩文件内容的情况下完成此操作?

我正在尝试加快读取 xml 文件以查找要删除的字符的过程。

标签: python-3.xxmlgziptarfile

解决方案


您必须解压缩、更改然后重新压缩文件。没有办法解决这个问题。

但是,这不一定包括将文件写入存储。您可能能够以流式方式进行您喜欢的更改,即所有内容都只在内存中完成,而无需在某处拥有完整的解压缩文件。Unix 使用管道来完成此类任务。

这是有关如何执行此操作的示例:

  1. 创建两个随机文件:
echo "hello world" > a
echo "hello world" > b
  1. 创建一个包含两者的压缩存档:
tar -c -z -f x.tgz a b
  1. 通过转换器传输未压缩存档的内容。不幸的是,我还没有找到任何基于 shell 的方法来执行此操作,但您还在标签中指定了 Python,并且使用该tarfile模块可以实现此目的:

这是文件tar.py

#!/usr/bin/env python3

import sys
import tarfile

tar_in  = tarfile.open(fileobj=sys.stdin.buffer,  mode='r:gz')
tar_out = tarfile.open(fileobj=sys.stdout.buffer, mode='w:gz')

for tar_info in tar_in:
  reader = tar_in.extractfile(tar_info)
  if tar_info.path == 'a':  # my example file names are "a" and "b"
    # now comes the code which makes our change:
    # we just skip the first two bytes in each file:
    reader.read(2)  # skip two bytes
    tar_info.size -= 2  # reduce size in info object as well
  # add the (maybe changed) file to the output:
  tar_out.addfile(tar_info, reader)

tar_out.close()
tar_in.close()

这可以这样调用:

./tar.py < x.tgz > y.tgz

y.tgz将再次包含这两个文件,但a在前两个字节中将被跳过(因此其内容将为llo world)。

您会注意到,您需要事先知道更改的结果大小。 tar旨在处理文件,因此它需要将入口文件的大小写入结果文件中每个入口文件之前的 tar 信息数据报,所以我看不出有什么办法。对于压缩输出,也无法在写入所有输出并调整文件大小后跳回。

但是,正如您所说的那样,在您的情况下这可能是可能的。

您所要做的就是提供一个类似文件的对象(可能是Popen对象的输出流),就像reader在我的简单示例中一样。


推荐阅读