6

根据 .Net 4.5 System.IO.Compression 中的 MSDN 是基于 zlib。
我现在正在尝试将当前基于互操作的读取从非 .NET 服务器的 zlib 压缩流更改为基于 BCL 的实现。
我的实现如下所示:

    var enc = new UTF8Encoding();            
        var readBytes = BufferSizeRaw;
        var outputBuffer = new byte[BufferSizeRaw];            
        var networkBuffer = _networkQueue.Take();
        var ms = new MemoryStream(networkBuffer.InputBuffer, 0, networkBuffer.UsedLength);
        using (Stream stream = new DeflateStream(ms, CompressionMode.Decompress))
            while (readBytes==BufferSizeRaw)
            {
                readBytes = stream.Read(outputBuffer, 0, outputBuffer.Length);                
                stringBuffer+= enc.GetString(outputBuffer, 0, readBytes);                
            }

我在 DeflateStream 上第一次调用解压/读取时收到以下异常:

块长度与其补码不匹配

基于互操作的调用使用var result=inflate(ref zStyream, ZLibFlush.NoFlush;
是否有人尝试过相同的方法或看到代码错误的原因,或者我的理解有误?我也尝试过截断前两个字节,但没有任何运气。
前几个字节是 20, 202, 177,13。

4

3 回答 3

19

上面的答案是正确的,但对“为什么”并不完全清楚。原始 ZLib 流的前两个字节提供有关使用的压缩类型的详细信息。System.Io.Compression 中的 Microsoft DeflateStream 类不理解这些。修复如下:

using (MemoryStream ms = new MemoryStream(data))
{
    MemoryStream msInner = new MemoryStream();

    // Read past the first two bytes of the zlib header
    ms.Seek(2, SeekOrigin.Begin);

    using (DeflateStream z = new DeflateStream(ms, CompressionMode.Decompress))
    {
        z.CopyTo(msInner);

在此示例中,数据是带有原始 Zlib 文件的 Byte[]。将其加载到 MemoryStream 后,我们只需“寻找”前两个字节。

如果您正在查看原始字节,该帖子解释了 Zlib 标头的外观。

zlib 标头是什么样的?

于 2014-02-04T04:59:26.410 回答
9

What are the first several bytes of the data you are trying to compress?

You might have zlib, gzip, or raw deflate data that you're trying to decode.

By the way, I highly recommend that you use DotNetZip's interface to zlib instead of NET 4.5's (or NET any version). NET 4.5 has bugs in that interface that Microsoft has declared that they won't fix (!).

于 2013-06-20T19:46:24.640 回答
5

这是 ProVega 答案的修订版,它将字节数组膨胀为字符串:

using (var stream = new MemoryStream(bytes,2, bytes.Length - 2))
using (var inflater = new DeflateStream(stream, CompressionMode.Decompress))
using (var streamReader = new StreamReader(inflater))
{
    return streamReader.ReadToEnd();
}
于 2014-04-18T15:21:41.170 回答