【问题标题】:Compressing and decompressing very large files using System.IO.Compressing.Gzip使用 System.IO.Compressing.Gzip 压缩和解压缩非常大的文件
【发布时间】:2018-04-23 21:18:25
【问题描述】:

我的问题可以用以下语句来描述:

  • 我希望我的程序能够压缩和解压缩选定的文件
  • 我有非常大的文件 (20 GB+)。可以安全地假设该大小永远不会适合内存
  • 即使压缩后的压缩文件可能仍然无法放入内存
  • 我想使用 .NET Framework 中的 System.IO.Compression.GzipStream
  • 我希望我的应用程序是并行的

由于我是压缩/解压缩的新手,我对如何做到这一点有以下想法:

我可以使用将文件拆分成块并分别压缩它们。然后将它们合并回一个完整的压缩文件。

关于这种方法的问题 1 - 压缩多个块,然后将它们合并在一起会给我正确的结果,即如果我要反转过程(从压缩文件开始,回到解压缩文件) 我会收到相同的原始输入吗?

关于这种方法的问题 2 - 这种方法对您有意义吗?也许你可以指导我去听一些关于这个话题的好讲座?不幸的是,我自己找不到任何东西。

【问题讨论】:

  • 为什么不直接从文件流通过 GZip 流传输数据,然后通过另一个文件流返回?任何一个文件都不需要放入内存中。
  • @glenebob 和 Cory 谢谢先生们,我明白了!我是否可以理解我可以有多个流压缩同一个文件,每个流都从不同的点开始?我收到 N 个流,然后将它们合并在一起?
  • 这可行,但结果不是有效的 GZip 文件。您将不得不发明一种文件格式。每个“块”本身就是一个有效的 GZip 文件。您的格式需要描述每个块,以便以后对各个块进行解压缩。
  • @CoryNelson gzip 压缩 可以 被并行化,但我认为这不是问题所在。它似乎只是关于控制内存使用。需要明确的是,任何有效 gzip 流的串联也是有效的 gzip 流。不需要“专有容器”。

标签: c# .net compression gzipstream system.io.compression


【解决方案1】:

您不需要为了限制内存使用而对压缩进行分块。 gzip 被设计为一种流格式,并且需要大约 256KB 的 RAM 来压缩。数据的大小无关紧要。输入可以是一个字节、20 GB 或 100 PB——压缩仍然只需要 256 KB 的 RAM。您只需将未压缩的数据读入,然后将压缩的数据写出,直到完成。

在您的图表中分块输入的唯一原因是利用多个核心进行压缩。这是您的数据量的一个很好的理由。然后,您可以完全按照您的描述进行操作。只要您以正确的顺序组合输出,解压就会重现原始输入。您始终可以连接有效的 gzip 流以生成有效的 gzip 流。我建议您使块相对较大,例如兆字节,因此压缩不会受到分块的明显影响。

解压不能以这种方式进行分块,但它的速度要快得多,因此即使可以这样做也几乎没有好处。解压通常是 i/o bound。

【讨论】:

  • 感谢您的回复!我确实希望程序使用多个核心,这是我想要满足的关键要求之一 - 能够使用多个核心进行压缩。
  • @Mark Adler 您能否编辑您的回复为第一段添加一些额外的参考?
  • @PavelRazgovorov 额外参考?
  • @MarkAdler 关于 gzip 使用的 256KB RAM。我不知道这是从哪里来的,我只是想知道更多细节。
  • @PavelRazgovorov 您应该为此发布一个新问题。还可以在这里查看内存占用:zlib.net/zlib_tech.html
猜你喜欢
  • 2013-05-28
  • 2022-07-06
  • 1970-01-01
  • 1970-01-01
  • 2010-09-05
  • 2010-12-14
  • 1970-01-01
  • 2011-09-01
  • 1970-01-01
相关资源
最近更新 更多