读取deflate流直到adler32校验和

时间:2017-09-15 11:52:33

标签: c# .net-core zlib deflate

所以.net没有ZlibStream所以我试图使用.net确实拥有的DeflateStream来实现我自己的。 DeflateStream显然也不支持使用字典,因此我也会在ZlibStream中跳过它。

写作效果很好,但我的Read方法有问题 这是我的Read方法:

public override int Read(byte[] buffer, int offset, int count)
{
    EnsureDecompressionMode();
    if (!_readHeader)
    {
        // read the header (CMF|FLG|optional DIC)
        _readHeader = true;
    }

    var res = _deflate.Read(buffer, offset, count);
    if (res == 0) // EOF
    {
        // read adler32 checksum
        BaseStream.ReadFully(_scratch, 0, 4);
        var checksum = (uint)_scratch[0] << 24 |
                       (uint)_scratch[1] << 16 |
                       (uint)_scratch[2] << 8 |
                       (uint)_scratch[3];
        if (checksum != _adler32.Checksum)
        {
            throw new ZlibException("Invalid checksum");
        }
    }
    else
    {
        _adler32.CalculateChecksum(buffer, offset, res);
    }
    return res;
}

其中:

  • _scratch是用作临时缓冲区的byte[4]
  • _deflateDeflateStream

Zlib的格式为CMF|FLG|optional DICT|compressed data|adler32|。所以我需要一种方法来在达到adler32时停止阅读。最初,我认为DeflateStream会在完成后返回EOF,但事实证明它会读取到底层流的EOF。所以它也会像adler32一样读取它的压缩数据。因此,当我尝试从adler32块内的BaseStream中读取if时,会抛出EOF异常。

那么我如何让DeflateStream停止阅读adler32,就像它的压缩数据一样,而不是那里的EOF或做同等的事情,以便我可以从adler32读取<Input value="{applicationModel>/propertyName}" editable="{viewModel>/editable}"/>没有压缩的BaseStream?

1 个答案:

答案 0 :(得分:0)

由于文件大小固定,您只需停留在base.Length - typeof(int)?必要时调整读缓冲区,然后读取未压缩的校验和。

喜欢:

public override int Read(byte[] buffer, int offset, int count)
{
    // read header...

    int res = -1;
    if (base.Position + count - offset > base.Length)
    {
        // EOF, skip the last four bytes (adler32) and read them without decompressing
        res = _deflate.Read(buffer, offset, count - sizeof(int));
    }
    else
    {
        res = _deflate.Read(buffer, offset, count);
    }

    // continue processing the data
}

未经过测试