2

我使用下面的代码来压缩文件,它们一直在增长而不是缩小。我压缩了一个 4 kb 的文件,它变成了 6 个。由于压缩开销,这对于一个小文件是可以理解的。我尝试了一个 400 mb 的文件,压缩后它变成了 628 mb。怎么了?查看代码。(.net 2.0)

Public Sub Compress(ByVal infile As String, ByVal outfile As String)
    Dim sourceFile As FileStream = File.OpenRead(inFile)
    Dim destFile As FileStream = File.Create(outfile)

    Dim compStream As New GZipStream(destFile, CompressionMode.Compress)

    Dim myByte As Integer = sourceFile.ReadByte()
    While myByte <> -1
        compStream.WriteByte(CType(myByte, Byte))
        myByte = sourceFile.ReadByte()
    End While

    sourceFile.Close()
    destFile.Close()
End Sub
4

4 回答 4

4

如果底层文件本身是高度不可预测的(已经压缩或很大程度上是随机的),那么尝试压缩它会导致文件变得更大。

从 400 到 628Mb 听起来不太可能作为扩展因子,因为 deflate 算法(用于 GZip)趋向于0.03% 的最大扩展因子。GZip 标头的开销应该可以忽略不计。

编辑:4.0 c# 版本表明压缩库已得到改进,不会导致不可压缩数据的显着扩展。这表明他们没有实施“回退到原始流块”模式。尝试使用 SharpZipLib 的库作为快速测试。当流无法通过放气压缩时,这应该为您提供接近相同的性能。如果它确实考虑移至该版本或等待 4.0 版本以获得更高性能的 BCL 实现。请注意,您得到的压缩不足强烈表明您没有必要尝试进一步压缩

于 2009-01-26T14:04:06.470 回答
2

您确定逐字节写入流是一个非常好的主意吗?它肯定不会有理想的性能特征,也许这也是 gzip 压缩算法的困惑所在。

此外,您尝试压缩的数据可能无法很好地压缩。如果我是您,我会尝试使用与文本文档大小相同的文本文档来尝试您的代码,其压缩比随机二进制文件要好得多。

此外,您可以尝试使用纯 DeflateStream 而不是 GZipStream,因为它们都使用相同的压缩算法(deflate),唯一的区别是 gzip 添加了一些额外的数据(如错误检查),因此 DeflateStream 可能会产生更小的结果。

我的 VB.NET 有点生疏,所以我宁愿不尝试在 VB.NET 中编写代码示例。相反,这就是你应该如何在 C# 中执行此操作,对于有一点经验的人来说,将它翻译成 VB.NET 应该相对简单:(或者也许擅长 VB.NET 的人可以编辑我的帖子并将其翻译成VB.NET)

FileStream sourceFile;
GZipStream compStream;

byte[] buffer = new byte[65536];
int bytesRead = 0;
while (bytesRead = sourceFile.Read(buffer, 0, 65536) > 0)
{
     compStream.Write(buffer, 0, bytesRead);
}
于 2009-01-26T14:01:19.407 回答
1

这是内置 GZipStream(和 DeflateStream)的已知异常。
我可以想到两种解决方法:

  • 使用替代压缩机。
  • 构建一些逻辑来检查“压缩”输出的大小并将其与输入的大小进行比较。如果更大,则丢弃输出并仅存储数据。

DotNetZip包含一个基于 zlib 托管端口的“固定”GZipStream。(它采用上面的方法#1)。Ionic.Zlib.GZipStream 可以用简单的命名空间交换替换应用程序中的内置 GZipStream。

于 2009-03-06T16:04:30.760 回答
0

谢谢大家的好答案。早些时候,我尝试压缩 .wmv 文件和一个文本文件。我将代码更改为 DeflateStream,它现在似乎可以工作了。干杯。

于 2009-01-26T14:36:21.053 回答