原始文件大于GZip解压缩文件

时间:2012-02-24 16:43:51

标签: c# .net gzip compression

所以我试图压缩一个字节数组(通过Stream)。 ExtendedStream只是我创建的一个与基本流接口的类(默认为MemoryStream)。如果我获取原始数据,压缩它,解压缩,然后将解压缩数据的大小与原始数据的大小(压缩前)进行比较,结果表明它小于原始数据。

原始长度:51695,压缩长度:26014,解压缩长度:48685。

我正在存储瓷砖(7个字节)。使用System.IO.Compression命名空间中提供的GZip类进行压缩。

    public static ExtendedStream GZipDecompress(ExtendedStream stream)
    {
        ExtendedStream outStream = new ExtendedStream();
        GZipStream decompressStream = new GZipStream(stream.BaseStream, CompressionMode.Decompress, true);
        int b = -1;

        while ((b = decompressStream.ReadByte()) != -1)
        {
            outStream.WriteByte((Byte)b);
        }

        outStream.Seek(0, SeekOrigin.Begin);
        return outStream;
    }

    public static ExtendedStream GZipCompress(ExtendedStream stream)
    {
        ExtendedStream outStream = new ExtendedStream(); // base stream is a memorystream
        GZipStream compressStream = new GZipStream(outStream.BaseStream, CompressionMode.Compress, true);
        compressStream.Write(stream.ToArray(), 0, (int)stream.Length);
        compressStream.Flush();
        outStream.Seek(0, SeekOrigin.Begin);
        return outStream;
    }

希望有足够的信息。

1 个答案:

答案 0 :(得分:1)

必须关闭压缩流;由于块问题,它无法写入所有数据:

public static ExtendedStream GZipCompress(ExtendedStream stream)
{
    ExtendedStream outStream = new ExtendedStream();
    using(var compressStream = new GZipStream(outStream.BaseStream, CompressionMode.Compress, false)) {
        compressStream.Write(stream.GetBuffer(), 0, (int)stream.Length);
    }
    outStream.Seek(0, SeekOrigin.Begin);
    return outStream;
}

注意:通常我会使用CopyTo(或手动循环)来执行写操作,但由于这是基于内存的GetBuffer()更便宜。

您的减压可以简单地说:

decompressStream.WriteTo(outStream);

在这两个方面,最大的问题(在这里咬过你)并没有丢弃你的一次性物品。你必须这样做;这是API的要求。为避免过早地处置外部流,请将“false”传递给GZipStream构造函数。例如:

using(var decompressStream = new GZipStream(stream.BaseStream, CompressionMode.Decompress, false)) {
    decompressionStream.CopyTo(outStream);
}