4

我想知道是否有人可以阐明一个让我发疯的问题:

我正在写一个压缩解压测试类。为了测试它,我将数据集序列化为内存流,对其进行压缩、解压缩并比较结果。

压缩很好,但解压缩是它碰到污垢的地方。这是解压功能:

    public static Stream GetUncompressedStreamCopy(Stream inStream)
    {
      Stream outStream = new MemoryStream();

      inStream.Position = 0;

      DeflateStream uncompressStream = new DeflateStream(inStream, 
        CompressionMode.Decompress, true);

      byte[] buffer = new byte[65536];

      int totalread = 0;
      int bytesread = 0;


      do {
        bytesread = uncompressStream.Read(buffer, 0, buffer.Length);
        totalread += bytesread;
        outStream.Write(buffer, 0, bytesread);
        Console.WriteLine("bytesRead: [{0}]\t outStream.Length [{1}]",
        bytesread, outStream.Length);
      } while (bytesread > 0);


      Console.WriteLine("total bytes read [{0}]", totalread);
      outStream.Flush();
      return outStream;
}

使用大小为 65536 的缓冲区,解压缩的流总是返回比未压缩的少一个字节。

现在,这将我带到了我正在与之抗争的第二个问题。对于某些缓冲区大小,uncompressStream.Read 即使仍有压缩数据要提取,也会返回 0。

对于这些情况,deflateStream.Read(s) 在 do{} 循环中只返回一次,然后返回一个等于 buffersize 的未压缩流,如果将 buffersize 增加一个字节,一切都很好(除了丢失的字节)。

缓冲区大小为 65536 的输出:(原始未压缩数据为 207833)

bytesRead: [65536]       outStream.Length [65536]
bytesRead: [65536]       outStream.Length [131072]
bytesRead: [58472]       outStream.Length [189544]
bytesRead: [18288]       outStream.Length [207832]
bytesRead: [0]           outStream.Length [207832]
total bytes read [207832]

189544的缓冲区大小(代码坦克的一些神奇数字)

bytesRead: [189544]      outStream.Length [189544]
bytesRead: [0]           outStream.Length [189544]
total bytes read [189544]
Unompressed stream size 189544

还要注意缓冲区大小 65536 的第三次读取,例如: bytesRead: [58472] 显然这也应该是 65536,因为缓冲区上还有数据吗?

任何想法将不胜感激。

蒂亚

  • 雅科
4

3 回答 3

7

您应该始终在压缩流上调用 Close()。请注意 Flush() 是不够的。我怀疑正因为如此,deflate 流缺少数据。

于 2009-10-22T14:29:23.410 回答
3

我的通灵能力告诉我,您实际上确实有一个有效的解压缩实现,但之前忘记了刷新压缩流。

于 2009-10-22T14:25:24.957 回答
0

好吧,我无法发现您的问题,但请遵循我之前为ICSharpCode.SharpZipLib编写的一些代码;

byte[] compressedData;
using(MemoryStream ms = new MemoryStream())
{
    Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION, true);
    Stream s = new DeflaterOutputStream(ms, deflater);
    s.Write(sendData, 0, sendData.Length);
    s.Close();
    compressedData = (byte[])ms.ToArray();
}

// ...

MemoryStream inflated = new MemoryStream();
using (Stream inflater = new InflaterInputStream(
    inputStream, new Inflater(true)))
{
    int count = 0;
    byte[] deflated = new byte[4096];
    while ((count = inflater.Read(deflated, 0, deflated.Length)) != 0)
    {
        inflated.Write(deflated, 0, count);
    }
    inflated.Seek(0, SeekOrigin.Begin);
}
byte[] content = new byte[inflated.Length];
inflated.Read(content, 0, content.Length);
于 2009-10-22T14:30:20.097 回答