【问题标题】:Accessing the internal buffer of a BinaryReader访问 BinaryReader 的内部缓冲区
【发布时间】:2014-10-30 02:24:34
【问题描述】:

我继承了BinaryReader 类。

我必须重写一些基本方法,例如 ReadUInt16

这个方法的内部实现是:

public virtual ushort ReadUInt16(){
   FillBuffer(2);
   return (ushort)(m_buffer[0] | m_buffer[1] << 8);
}

我正在读取的二进制文件被组织为高字节优先(大端),我继承自 BinaryReader 也是因为我必须添加更多功能。 无论如何,我想在子类本身中实现交换。

是否有其他方法可以访问m_buffer 或替代方法而不使用反射或其他消耗资源?
也许我应该覆盖FillBuffer 并备份偷看的字节?或者也许只是忽略它?会不会有副作用?有没有人遇到过这个问题?谁能解释为什么FillBuffer 不是内部的?是否需要始终填充缓冲区或可以跳过?既然它不是内部的,为什么不同时实现 m_buffer 字段的受保护吸气剂?

这是FillBuffer的实现。

protected virtual void FillBuffer(int numBytes) {
    if (m_buffer != null && (numBytes < 0 || numBytes > m_buffer.Length)) {
        throw new ArgumentOutOfRangeException("numBytes", 
            Environment
            .GetResourceString("ArgumentOutOfRange_BinaryReaderFillBuffer"));
    }
    int bytesRead=0;
    int n = 0;

    if (m_stream==null) __Error.FileNotOpen();

    // Need to find a good threshold for calling ReadByte() repeatedly
    // vs. calling Read(byte[], int, int) for both buffered & unbuffered
    // streams.
    if (numBytes==1) {
        n = m_stream.ReadByte();
        if (n==-1)
            __Error.EndOfFile();
        m_buffer[0] = (byte)n;
        return;
    }

    do {
        n = m_stream.Read(m_buffer, bytesRead, numBytes-bytesRead);
        if (n==0) {
            __Error.EndOfFile();
        }
        bytesRead+=n;
    } while (bytesRead<numBytes);
}

【问题讨论】:

    标签: c# binary endianness binaryreader


    【解决方案1】:

    尝试访问内部缓冲区不是一个好主意。为什么不这样做:

    var val = base.ReadUInt16();
    return (ushort)((val << 8) | ((val >> 8) & 0xFF));
    

    比直接从缓冲区读取稍慢,但我严重怀疑这会对应用程序的整体速度产生重大影响。

    FillBuffer 显然是一个实现细节,出于某种原因,Framework 团队决定他们需要制作protected,可能是因为其他一些Framework 类利用了BinaryReader 的内部工作原理。由于您知道它所做的只是填充内部缓冲区,并且您的派生类无法访问内部缓冲区,因此如果您决定自己重写读取实现,我建议您忽略该方法。调用它对你没有任何好处,可能会给你带来很大的伤害。

    你可能对我几年前写的series of articles 感兴趣,我在其中实现了一个BinaryReaderWriter 类,它本质上是一个BinaryReaderBinaryWriter 结合在一起,并允许你随机读/写访问到底层流。

    【讨论】:

    • 您说在尝试访问缓冲区之前需要调用该方法,但是如果缓冲区根本无法访问怎么办?他们应该将此方法设为内部方法或为缓冲区提供 getter 包装器。我更喜欢性能,因为我正在处理大型二进制文件,我将忽略 FillBuffer。请在您的回答中更具体地参考它,对于其他用户来说应该更清楚。您是否认为保存交换是多余的优化(我需要覆盖所有数字阅读器)。
    • 是的,我相信保存交换是多余的优化。与从磁盘文件读取数据所需的时间相比,几百万次交换算不了什么。至于FillBuffer 方法,我不担心。这显然是一个实现细节,出于某种未知原因,框架团队认为他们需要公开。可能是因为不同的 .NET 类使用它。正如您所说,由于它的功能是填充派生类无法访问的内部缓冲区,因此调用它对您没有任何好处。
    • 吉姆,将&amp; 0xFF 包含到刚刚右移的位有什么意义?是不是和不使用的结果一样?你能否请我参考一篇解释这一点的文章?顺便说一句,我刚刚订阅了你的博客,我喜欢它!
    • @Shimmy:&amp;0xFF 可能不需要。我怀疑我在写这篇文章时正在考虑转移int
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-29
    • 2012-12-08
    相关资源
    最近更新 更多