首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >读取放气流,直到adler32校验和

读取放气流,直到adler32校验和
EN

Stack Overflow用户
提问于 2017-09-15 11:52:33
回答 2查看 833关注 0票数 1

因此,.net没有ZlibStream,所以我尝试使用DeflateStream实现自己的ZlibStream,而.net确实有。DeflateStream显然也不支持使用字典,所以我在ZlibStream中也跳过了这一点。

写作很好,但我的阅读方法有问题。

下面是我的阅读方法:

代码语言:javascript
复制
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,或者做一些类似的事情,这样我就可以不用压缩从BaseStream读取adler32了?

EN

回答 2

Stack Overflow用户

发布于 2017-09-15 12:06:49

既然文件的大小是固定的,你就不能在base.Length - typeof(int)上停下来吗?必要时调整读缓冲区,然后读取未压缩校验和.

有点像:

代码语言:javascript
复制
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
}

未测试

票数 0
EN

Stack Overflow用户

发布于 2022-03-02 10:16:00

通过源代码这里DeflateStream读取8K块中的输入数据:-/,所以如果您的输入文件很小,它看起来就像是在读取文件的末尾,

但是,DeflateStream实例有一个私有成员_inflater,其中有一个私有成员_zlibStream,该成员有一个属性AvailIn,该属性返回输入缓冲区中可用的字节数。IOW,这是读取的字节数,所以通过使用反射获取这些私有部分,我们可以将文件指针向后移动那么多字节,将其返回到应该保留的位置,即刚刚过了压缩数据的末尾。

这段代码是F#,但是应该清楚地知道发生了什么:

代码语言:javascript
复制
// zstream is the DeflateStream instance
let inflater = typeof<DeflateStream>.GetField( "_inflater", BindingFlags.NonPublic ||| BindingFlags.Instance ).GetValue( zstream )
let zlibStream = inflater.GetType().GetField( "_zlibStream", BindingFlags.NonPublic ||| BindingFlags.Instance ).GetValue( inflater )
let availInMethod = zlibStream.GetType().GetProperty( "AvailIn" ).GetMethod
let availIn: uint32 = unbox( availInMethod.Invoke( zlibStream, null ) )
// inp is the input file
inp.Seek( -(int64 availIn), SeekOrigin.Current ) |> ignore
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46238944

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档