【问题标题】:On-the-fly GZIP Filesize Estimates即时 GZIP 文件大小估计
【发布时间】:2021-01-12 00:04:40
【问题描述】:

我正在尝试编写一个程序,在 GZIP 压缩时将大型数据集拆分为目标大小 target 或更小的较小数据集。

到目前为止,我想出的最好方法是只跟踪我迄今为止看到的数据的原始字符串长度,并通过一些 GZIP 压缩比猜测来估计最终大小。不过,这会导致一些相当大的偏差。大多数情况下,估计大小在我的目标的 20% 以内,但有时我会得到比我的估计预测大 100% 的文件。

此外,压缩估计似乎是周期性的。因此,如果我想要 10MB 的文件,我最终会得到大部分 10MB 的文件,然后在文件大小分布中集中为 20、30、40 MB。

那么,有没有什么方法可以对输出压缩文件的大小进行即时有根据的猜测,而到目前为止还没有实际压缩组装的流?是否可以使用不同的压缩格式?我不需要它是完美的,但我确实希望它接近。

伪代码示例(实际上我可以使用 java、python 或 scala 来完成此操作。这只是说明性的):

COMPRESSION_RATIO_GUESS = 20
targetSize = 10 * 1024 * 1024

with open("bigfile.txt","r") as f:
    so_far = 0
    for line in f.readlines():
        so_far += len(line)
        if so_far/COMPRESSION_RATIO_GUESS > targetSize:
            # start new file, write rows so far
        
        
    

【问题讨论】:

    标签: compression gzip


    【解决方案1】:

    正如您已经发现的那样,这样的估计是尝试实现目标的糟糕方法。还有更好的方法。

    我们需要了解更多有关您的申请的信息。您正在压缩的数据集的大小是多少?您想获得什么样的目标尺寸?你想多接近目标尺寸?您可以在哪里拆分您的数据集,以字节距离为单位,这些拆分的频率是多少?

    我会推荐一种相对简单的方法,它使用 zlib 清除块的能力。您将压缩数据集的某些部分,并刷新输出。保存长度和压缩数据结束的位置。 (您可以刷新到字节边界。)对另一部分重复。继续,直到你超过你的目标。然后回到你上次刷新的时间,并用最后一个块和预告片完成那个流。现在使用您刚刚备份的数据创建一个新文件。

    根据您的数字,可以选择您在一个块中压缩的数量,以允许您接近目标,并且不会显着影响压缩率。

    fitblk 所使用的,有更复杂的方法可以让您尽可能接近目标。 fitblk 压缩超过目标,然后解压缩到目标。然后它只重新压缩该数量,然后第三次解压缩并压缩,以获得填充到目标的几个字节。

    【讨论】:

    • 我喜欢收集和刷新 zlib 块的想法,我会看看我能用它做什么。我的实际用例是尝试从 Spark/Scala 应用程序中获取大致确定的输出文件大小。我正在遍历分区中的行并用新的重新分区列标记它们,当 Spark 准备好写入输出时,该列可用于将行分组到特定文件中。所以或多或少是我上面描述的过程,但在实践中更复杂。
    • 因为我忘了回答你的第一个问题,所以我将数据分区(几 GB)分成相对较小的文件,大约 10-50MB。
    • 好。典型的块大小以 KB 为单位,因此您可以非常接近您的目标。您一次可以只输入 1 MB 的压缩数据,并且由于刷新而对压缩率几乎没有影响。
    猜你喜欢
    • 1970-01-01
    • 2012-03-17
    • 1970-01-01
    • 1970-01-01
    • 2014-06-26
    • 2012-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多