GZipStream和DeflateStream生成的文件更大

9

我正在尝试在C#中使用deflate/gzip流进行压缩,但似乎压缩后的文件比之前还要大。

例如,我压缩了一个900ko的docx文件,但它生成了一个1.4Mo的文件!

而且我尝试过的每个文件都是如此。

也许我在操作方式上有误?这是我的代码:

  FileStream input = File.OpenRead(Environment.CurrentDirectory + "/file.docx");
  FileStream output = File.OpenWrite(Environment.CurrentDirectory + "/compressedfile.dat");

  GZipStream comp = new GZipStream(output, CompressionMode.Compress);

  while (input.Position != input.Length)
      comp.WriteByte((byte)input.ReadByte());

  input.Close();

  comp.Close(); // automatically call flush at closing
  output.Close();

1
你应该意识到,不存在一种压缩方法可以将任意的输入至少压缩一个字节。因此,特别是当你试图压缩已经接近随机的数据(例如预压缩数据)时,可能会看到尺寸增加。 - Joey
3
.docx已经使用ZIP压缩进行了压缩(尝试将其重命名为.zip并进行探索)。如果再进行第二层压缩,我会感到惊讶,因为这不太可能会有任何好处。 - spender
它应该只在刷新时有效地进行压缩,因此它不应该改变任何东西。 - kite
@spender > 我不知道,我会尝试使用另一种文件格式。 - kite
有一个与微软相关的错误报告,涉及DeflateStream增加先前压缩数据流的现象:https://connect.microsoft.com/VisualStudio/feedback/details/93930/gzipstream-deflatestream-fail-to-check-for-incompressible-data。目前它被标记为“已关闭-外部”。我不知道这是什么意思。 - Cheeso
显示剩余2条评论
5个回答

7

对我来说,这样的差异似乎很奇怪,但您应该记住 docx 本身已经在 ZIP 中进行了压缩,因此没有必要再次压缩它,结果通常会更大。


是的,谢谢,我不知道这个,所以才会出问题 :) 尝试使用 .txt 和其他格式,似乎效果更好。但是它仍然无法在自制的序列化文件类型上运行... 但是最终并不重要,我只是想看看如何使用这些压缩流 :) - kite

2
首先,与zip、7z等格式相比,deflate/gzip流在压缩方面表现得非常糟糕。
其次,docx(以“x”结尾的所有MS文档格式)只是.zip文件。将.docx重命名为.zip即可揭示其中的烟雾和镜子。
因此,当你运行deflate/gzip在docx上时,它实际上会使文件变大。(就像对具有高压缩级别的已压缩文件进行低压缩级别的zip一样。)
但是,如果你在HTML或文本文件或未经压缩的其他文件上运行deflate/gzip,则它实际上会做得非常好。

是的,谢谢。就像在其他评论中所说的那样,我不知道docx已经被压缩了。当然,7z和其他库更好,但我只是想尝试一下这些工具,看看它们能做什么。 - kite
2
这似乎是一个完全无效的评论:“与zip、7z等相比,deflate/gzip流在压缩方面非常糟糕”。事实上,99%的zip文件使用DEFLATE作为压缩格式。因此,zip不能比DEFLATE更好,因为它会用元数据增强压缩流。 - Cheeso
DeflateStream实际上增加了先前压缩数据的大小的现象是一个错误的主题,该错误在2006年向Microsoft提出:https://connect.microsoft.com/VisualStudio/feedback/details/93930/gzipstream-deflatestream-fail-to-check-for-incompressible-data - Cheeso

0

虽然其他人已经指出,你指定的示例文件已经被压缩了,但最大的问题是要理解,与大多数压缩实用程序不同,DeflateStreamGZipStream类只是尝试对数据流进行标记/压缩,而没有智能地意识到所有附加标记(开销)实际上增加了所需数据的数量。Zip、7z等则足够聪明,知道如果数据基本上是随机熵(几乎无法压缩),它们只需将数据“按原样”存储(存储,而不是压缩),而不是尝试进一步压缩。


1
这是不正确的:Zip、7z等压缩格式足够智能,如果数据是大部分随机熵(几乎无法压缩),它们会简单地将数据“原样”存储(存储,而非压缩),而不是尝试进一步压缩。 ZIP仅仅是一个文件格式,它并不“知道”任何东西。生成ZIP文件的程序可能会执行您所描述的操作,但ZIP格式本身并不会。 - Cheeso
1
DeflateStream实际上会扩大先前压缩数据的大小的现象是一个已经向Microsoft报告的错误的主题:https://connect.microsoft.com/VisualStudio/feedback/details/93930/gzipstream-deflatestream-fail-to-check-for-incompressible-data - Cheeso
我不是在谈论格式(天哪),而是在谈论将数据以相应格式写入的压缩工具。 - Michael

0

我在压缩包含jpg数据的数据库时遇到了同样的问题。我尝试了dotnetzip - 一个可替换的解决方案,并获得了不错的压缩效果(也支持紧凑框架!):

MS : 10MB -> 10.0MB
DNZ: 10MB ->  7.6MB

-2
我认为 GzipStream 和 DeflateStream 并不适用于压缩文件。你可能会更幸运地使用一个像SharpZipLib这样的文件压缩器。

它们被用来进行压缩和解压缩。我目前正在阅读MCTS 70-536认证书,它们在那里被这样使用^^ - kite
GZipStream类提供用于压缩和解压缩流的方法和属性。它们是用来干什么的?http://msdn.microsoft.com/en-us/library/system.io.compression.gzipstream.aspx - Andrey
它们在压缩文件方面表现得非常出色,对于许多情况来说比zip更方便,因为它们直接处理文件而不是创建存档,并且您可以直接从Web服务器输出它们,而无需每次都进行实时压缩。将“.gz”附加到名称中(在原始扩展名之后而不是替换它)是gzip文件的常见做法。这并不是说SharpZipLib在许多情况下不更好。 - Jon Hanna
@kite:我曾在微软的PSS工作,并协助开发了一些测试。如果它出现在MS认证书中,那么它同样有可能是一种可怕的做事方式 :) 尽管如此,没有任何压缩器能够使已经压缩过的文件变得更小。 - Dave Swersky
1
@Dave Swersky:这是一个相当大胆的说法。可以使用Huffman编码来压缩文件,然后进行zip压缩以使其更小。根据您的第一种压缩技术有多糟糕,第二种压缩技术可能会使其变得更好或更差。 - astellin
1
@Excel:我承认我错了。我想结合两种不同类型的压缩可能会增加总体比率,但我要说使用ZIP两次是行不通的。 - Dave Swersky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接