我需要将整数值序列化为字节数组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]
是其缓冲区中第一个字节的最低有效位,而我需要它是缓冲区中第一个字节的最高有效位。
答案 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();
}
}