【问题标题】:In-place modification of gzip filesgzip文件的就地修改
【发布时间】:2021-09-15 17:16:19
【问题描述】:

我需要修改一个 gzip 格式的制表符分隔文件。我可以从输入读取并将修改后的读取写入输出文件:

output = tempfile.NamedTemporaryFile(mode="w", delete=False)
with gzip.open(input, "rb") as in_file,\
     gzip.open(output, "wb") as out_file:
    for l in in_file:
        split_line = l.split("\t")
        if split_line[0] == "hello":
            split_line[0] = "hi"
        out_file.write("\t".join(split_line))

我使用的 gzip 压缩文件的大小为 100 GB,因此仅将整个文件重写为不同的文件以修改子集并不理想。因此,我对修改文件就地(即,在您遍历原始文件时修改原始文件)的解决方案感兴趣。

【问题讨论】:

  • gzip 压缩格式不允许就地修改。
  • 真的不可能。它是一种流压缩算法,因此如果您更改文件中的某些内容,那么它之后的所有内容都会受到影响。
  • 您可能是时候为您的数据考虑一种不同的格式了。也许是 SQLite,或者甚至是其中一个 SQL 服务器。
  • 我的意思是,如果您有意构建您的 gzip 文件以使压缩表每隔一段时间重置一次,然后在新内容大于旧内容时使用填充,它是 理论上可以实现,但理论上可以!=实用。
  • (请注意,一些较新的文件系统允许您在块边界的中间扩展文件,因此如果您将定期压缩表重置与该功能相结合,您甚至可以在文件中间添加新数据当它更大时,但您仍然需要处理使所有内容正确对齐插入块之后......这一切都取决于一个足够现代的文件系统)。

标签: python gzip in-place


【解决方案1】:

对于普通的 gzip 文件,当然不是。您唯一的选择是将 gzip 文件读取到您想要修改的位置,进行修改,然后重新压缩其余部分。在进行切割时需要注意,移除包含切割的放气块,然后从那里重新压缩,将剩余的放气块附加到正确的位位置。

理论上,您可以准备一个大的 gzip 文件,以便可以就地进行此类修改。您需要将 gzip 文件分解为独立的块,其中每个块开头的历史记录将被丢弃。 (pigz 使用 --independent 选项执行此操作。)您还需要在每个独立块的末尾插入几个空块或其他填充空间,以允许独立块的长度变化,以便修改后的结果可以适合回到完全相同的字节数。您可以插入 5 字节和 2 字节的空块,如果您有足够的数量,它们的组合应该能够容纳任何少量的字节数差异。

您将需要这些独立块的位置的单独索引,否则您将花费​​时间搜索它们,再次使时间取决于文件的长度。

为了不显着影响 gzip 文件的整体压缩率,您可能希望独立块的未压缩大小约为 128K 字节或更大。任何修改都需要重新压缩整个独立块。

您还需要更新 gzip 文件末尾的 CRC 和长度。我认为有一种方法可以在不为整个文件重新计算的情况下更新 CRC,但我必须考虑一下。如果文件的长度没有改变当然是可能的,但是如果你插入或删除字节,它就会变得更加棘手。

要尝试将方形 gzip 钉子放入圆形随​​机修改孔中,这将是大量的工作。它表明您只是为应用程序使用了错误的格式。为你想做的事情找到不同的格式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 2012-10-26
    • 1970-01-01
    • 1970-01-01
    • 2016-10-16
    相关资源
    最近更新 更多