二进制读取器 - 如何读取单个位?

4

案例:
再次尝试通过我的网卡捕获数据包,我开发了两个扩展程序来捕获可变数量的位。

    public static string ReadBits ( this BinaryReader Key , int Value )
    {
        BitArray _BitArray = new BitArray ( Value );

        for ( int Loop = 0 ; Loop > Value ; Loop++ )
        {
/* Problem HERE ---> */   _BitArray [ Loop ] = Key . ReadBoolean ( );
        }

        return BitConverter . ToString ( _BitArray . ToByteArray ( ) );
    }

    public static byte [ ] ToByteArray ( this BitArray Key )
    {
        byte [ ] Value = new byte [ ( int ) Math . Ceiling ( ( double ) Key . Length / 8 ) ];
        Key . CopyTo ( Value , 0 );
        return Value;
    }

问题:

_BitArray [ Loop ] = Key . ReadBoolean ( );  

我试图读取单个位,但参考MSDN文档,它将流位置提前了1个字节而不是1个位!!!

从当前流中读取布尔值,并将流的当前位置向前移动一个字节

问题:
我真的可以仅捕获1位并将流位置提前1位吗?
请给我建议或想法 :)

谢谢,

3个回答

7
不,流定位是基于字节步进的。您可以编写自己的流实现来进行位定位。
class BitReader
{
    int _bit;
    byte _currentByte;
    Stream _stream;
    public BitReader(Stream stream)
    { _stream = stream; }

    public bool? ReadBit(bool bigEndian = false)
    {
      if (_bit == 8 ) 
      {

        var r = _stream.ReadByte();
        if (r== -1) return null;
        _bit = 0; 
        _currentByte  = (byte)r;
      }
      bool value;
      if (!bigEndian)
         value = (_currentByte & (1 << _bit)) > 0;
      else
         value = (_currentByte & (1 << (7-_bit))) > 0;

      _bit++;
      return value;
    }
}

1
那么,位的顺序呢?最低位优先还是最高位优先? - Ahmed Ghoneim
2
好的,已添加 bigEndian 支持。 - Pavel Krymets
2
更改方法签名以返回可空布尔值,如果流返回EOS(-1),则该方法返回null。 - Pavel Krymets

3

不,无法将 Stream 实例提前一位。 Stream 类型支持的最小粒度为一个 byte

你可以编写一个对 Stream 进行包装的类,通过操纵和缓存一字节的移动来提供一位粒度。

class BitStream { 
  private Stream _stream;
  private byte _current;
  private int _index = 8;


  public byte ReadBit() {
    if (_index >= 8) {
      _current = _stream.ReadByte();
      _index = 0;
    }
    return (_current >> _index++) & 0x1;
  }
}

注意:这将从右侧读取字节并转换为位。如果您想从左侧读取,需要稍微更改 return 行。

1

读取1个字节并使用位掩码将其转换为8元素布尔数组


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接