【问题标题】:Is it possible to remove characters from a compressed file without extracting it?是否可以在不提取压缩文件的情况下从压缩文件中删除字符?
【发布时间】:2020-03-03 14:46:54
【问题描述】:

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

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

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

【问题讨论】:

  • 您想更改压缩文件的内容,但不想解压缩(然后重新压缩)它? gzip 压缩不是这样工作的。
  • 当您说“提取”时,您的实际意思是“写入磁盘”吗?如果是这样,应该可以在不向文件系统写入任何内容的情况下实现您想要的,但是您必须解压缩数据,删除不需要的字符,然后重新压缩它。
  • 如果不写入磁盘,它在哪里解压?在记忆中?如果是这样,在处理大文件时这可能会成为一个问题?我正在尝试更好地理解 gzip。

标签: python-3.x xml gzip tarfile


【解决方案1】:

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

但是,这并不一定包括将文件写入到存储中。您可能能够以 流式传输 方式进行您喜欢的更改,即一切都只在内存中完成,而在某处没有完整的解压缩文件。 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 2018-04-12
    • 1970-01-01
    相关资源
    最近更新 更多