使用MSB优先位顺序时,保留BitArray中的位顺序

时间:2014-05-18 01:23:17

标签: .net endianness bitarray

我需要将整数值序列化为字节数组Byte[],这样输入值的最高有效位也是目标数组中最重要的位。它还需要允许存储位置的每位(而不是每字节)偏移量。

这是一个简单的例子,我写了一个与字节边界对齐的整数(以MSByte-first,MSbit-first-order):

Byte[] buffer = new Byte[99];
Encode( buffer, 0, 0x1234 ); // Encode the value 0x1234 inside buffer at bit-offset 0.
Assert.AreEqual( buffer[0], 0x12 ); // The integer value is stored most-significant-byte first
Assert.AreEqual( buffer[1], 0x34 );

这里有类似的东西,但偏移 1位

Array.Initialize( buffer ); // Reset the buffer's bytes to 0.
Encode( buffer, 1, 0x0102 ); // Encode 0x0102 at bit-offset 1
// In binary 0x0102 is 00000001 00000010, but the final buffer will be this: 00000000 10000001 00000000
Assert.AreEqual( buffer[0], 0x00 ); // The first byte will be zero
Assert.AreEqual( buffer[1], 0x81 ); // 10000001 == 0x81
Assert.AreEqual( buffer[2], 0x00 );

我目前正在使用BitArray实例,但是BitArray会在字节内反转位顺序,即。 bitArray[0]是其缓冲区中第一个字节的最低有效位,而我需要它是缓冲区中第一个字节的最高有效位。

1 个答案:

答案 0 :(得分:0)

我能解决这个问题的唯一方法是实现我自己的BitArray类,它保留了最低至最低位的顺序。

我觉得自己被骗了,因为在内部我使用Boolean[]来存储位值,而不是像Int32[]那样存储BitArray,但我对我得到的性能感到满意。

这是我使用的逻辑:

/// <summary>A bit-array that works with bytes in big-endian order (that is, this[0] == big-endian-bit of the first byte).</summary>
public class BitArray2 : IEnumerable<Boolean> {

    private Boolean[] _bits;

    public BitArray2(Int32 byteCount, Boolean initialValue) {

        this._bits = new Boolean[ byteCount * 8 ];
        for(int i=0;i<this._bits.Length;i++) {
            this._bits[i] = initialValue;
        }
    }

    public BitArray2(Byte[] copyFrom) {

        this._bits = new Boolean[ copyFrom.Length * 8 ];

        for(int i=0;i<copyFrom.Length;i++) {
            Byte b = copyFrom[i];

            this._bits[ (i*8) + 0 ] = (b & 0x80) == 0x80;
            this._bits[ (i*8) + 1 ] = (b & 0x40) == 0x40;
            this._bits[ (i*8) + 2 ] = (b & 0x20) == 0x20;
            this._bits[ (i*8) + 3 ] = (b & 0x10) == 0x10;
            this._bits[ (i*8) + 4 ] = (b & 0x08) == 0x08;
            this._bits[ (i*8) + 5 ] = (b & 0x04) == 0x04;
            this._bits[ (i*8) + 6 ] = (b & 0x02) == 0x02;
            this._bits[ (i*8) + 7 ] = (b & 0x01) == 0x01;
        }
    }

    public Boolean this[Int32 bitIndex] {
        get { return this._bits[bitIndex]; }
        set { this._bits[bitIndex] = value; }
    }

    public void CopyTo(Byte[] buffer) {

        for(int i=0;i<_bits.Length;i+=8) {

            Int32 destIndex = i / 8;

            Byte b = 0;
            if( this._bits[ i + 0 ] ) b |= 0x80;
            if( this._bits[ i + 1 ] ) b |= 0x40;
            if( this._bits[ i + 2 ] ) b |= 0x20;
            if( this._bits[ i + 3 ] ) b |= 0x10;
            if( this._bits[ i + 4 ] ) b |= 0x08;
            if( this._bits[ i + 5 ] ) b |= 0x04;
            if( this._bits[ i + 6 ] ) b |= 0x02;
            if( this._bits[ i + 7 ] ) b |= 0x01;

            buffer[ destIndex ] = b;
        }
    }

    public IEnumerator<Boolean> GetEnumerator() {
        // See http://stackoverflow.com/questions/1272673/obtain-generic-enumerator-from-an-array
        return ((IEnumerable<Boolean>)this._bits).GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator() {
        return this.GetEnumerator();
    }
}