为了解析非托管数据的二进制流,我必须重新创建数据类型。数据已压缩,这意味着我读取了2个字节,这些字节实际上代表6位byte
值和10位short
值。
我要做的就是将一个位序列从一个值复制到另一个。我知道源值和目标值的起始位和长度。到目前为止,我已经采取了两种方法来复制正确的位,但是以某种相反的顺序。
byte BitwiseCopy(short value, int sourceStartBit, int destStartBit, int bitCount)
{
short result = 0;
for (int i = 0; i < bitCount; i++)
//result |= (byte) (value & (1 << sourceStartBit + i) | (result & (1 << (destStartBit + bitCount) - i)));
result |= (short) (value & (1 << sourceStartBit + i));
return (byte) (result >> ((destStartBit - bitCount) + sizeof(byte) * 8));
}
对于我的测试场景,我使用具有以下值的短裤:
0000 0000 1101 0011
^15 ^0
我的目标是将此short的第4个-第7个位复制到字节的 0-3rd 位。 / p>
当我使用注释行(在return子句中没有代码)方法或当前突出显示的方法时,总是会得到以下结果:
0000 1011
^7 ^0
所以我想要的只是反转。我敢肯定它很小,但是我在这里俯瞰什么?我不明白为什么它会颠倒顺序。移位方法(直接按位复制并将其移位到正确的位置)不应该反转它吗?
编辑:
方法始终具有类型为short
的输入。我有3个参数: sourceStart 是我从输入值(从低到高)开始复制的位, destStart 是我要复制到目标的位(可以是字节,也可以是短字节-为此,我将使用两种特定的方法)和 bitCount ,这是我要复制的位数(从低到高的顺序)。
方法必须以正确的顺序复制位。因此,例如,CopyBitwise(input, 4, 0, 4)
应该返回(左:高,右:低阶)0000 1011
,输入如下:
input [short]: ... 1011 0110
^8th ^0th
另一个:
input [short]: 1011 0110 0100 0111
^15th ^0th
^end ^start
CopyBitwise(input, 7, 3, 5)
应该导致
0011 0000
^8th ^0th
^end ^start
答案 0 :(得分:1)
您不需要为此循环! 这应该可以解决问题:
byte BitwiseCopy(short value, int sourceStartBit, int destStartBit, int bitCount){
byte result = (byte) ((value >> sourceStartBit) << destStartBit);
result &= (byte) ~(0xff << bitCount); // mask for zeros at the left of result
return result;
}
答案 1 :(得分:0)
听起来您想要的是剪切给定短裤的子序列。这可以通过 masking 来实现。如果要从以下位序列中剪切突出显示的位:1011 0110
0100
0111
,则可以这样做通过&
和0000 0000 1111 0000
来实现。
1011 0110 0100 0111
& 0000 0000 1111 0000
= 0000 0000 0100 0000
然后可以移位结果位,以使被屏蔽的位从所需位置(此处为1)开始
0000 0000 0100 0000 >>
· 0000 0000 0100 000 >>
·· 0000 0000 0100 00 >>
··· 0000 0000 0100 0
byte BitwiseCopy(short value, int sourceStartBit, int destStartBit, int bitCount)
{
ushort mask = 0; //Start with 0
mask = (ushort)~mask; //Invert to get all 1s
mask >>= sizeof(ushort)*8 - bitCount; //Shift right, until we have bitCount bits left
mask <<= sourceStartBit; //Shift back left, to make sure the bits are in the right place
ushort result = (ushort)value;
result &= mask; //Mask out the bits we want
//Shift the remaining bits into the desired position
if (sourceStartBit < destStartBit)
{
result <<= destStartBit - sourceStartBit;
}
else
{
result >>= sourceStartBit - destStartBit;
}
return (byte)result;
}
首先,我们组装位掩码。为此,我们从0
开始,然后将所有位取反以得到所有位。我们可以从0xFFFF
开始,但是通过这种方式,如果您切换到不同长度的输入,代码仍然可以工作。
然后,我们将蒙版移动到仅剩bitCount
1
个。对于此步骤,重要的是我们的掩码是 unsigned 整数类型。如果您使用的是带符号的值,则位移会从左侧向左移动新的1
。
要完成我们的遮罩,我们将其向左移以正确定位。
接下来,我们将掩码应用于我们的值以切出不需要的位。
最后,我们将结果移到所需位置;在这里再次重要的是使用 unsigned 移位,以确保没有错误的1
从左侧移位。
这是使用参数调用方法时发生的示例
(0b1011_0110_0100_0111, 7, 3, 5)
,如您的第二个示例。
mask:
0000 0000 0000 0000 ~x
= 1111 1111 1111 1111 x>>(16 - 5)
= 0000 0000 0001 1111 x<<7
= 0000 1111 1000 0000
result:
1011 0110 0100 0111 x&mask
0000 0110 0000 0000 x>>(7-3)
0000 0000 0110 0000
编辑1:
将代码中的此行mask >>= bitCount - sizeof(ushort)*8;
更正为mask >>= sizeof(ushort)*8 - bitCount;
。
编辑2: 我也弄乱了下面的行,也修复了该行。这就是我仅测试一个案例的结果。
编辑3: 添加了分步示例。
答案 2 :(得分:0)
这应该正常工作。 首先为所需的位创建掩码,然后将其移至所需位置。请注意,由于移位运算符必须为正数,所以要进行两次移动。
byte BitwiseCopy(short value, int sourceStartBit, int destStartBit, int bitCount)
{
short mask = (short)((0xFFFF >> (16-bitCount)) << sourceStartBit);
short result = (short)(((value & mask) >> sourceStartBit) << destStartBit);
return (byte)result;
}