在解码某些视频流标准时,我注意到很多实例,其中Integer值的位以2-6字节提供,但由保留位分隔,如下所示:
// Specification (16 bits)
// -----------------------
// Reserved 1 bit
// Value A [6-7] 2 bit
// Reserved 2 bit
// Value A [4-5] 2 bit
// Reserved 3 bit
// Value A [0-3] 4 bit
// Reserved 2 bit
例如,值185(10111001
或0xB9
)将在两个字节数组中按如下方式存储:
01000110 00100100
我知道这很疯狂,但这就是这些人编码数据流的方式。可以使用以下位操作提取它
int w = 0;
w |= (0x60 & data[0]) >>> 5; // extract the first 2 bits shifted to the front
w <<= 2; // bump them up 2 bits for the next section
w |= (0x06 & data[0]) >>> 1; // extract the next 2 bits shifted to the front
w <<= 4; // bump them up 4 bits for the last section
w |= (0x3C & data[0]) >>> 2; // extract the last 4 bits shifted to the front
// w now will equal 10111001 (185)
我希望能够做的是创建一个方法,接受一个长度不确定的字节数组,一个Int代表一个位的掩码,它构成我们试图从提供的规范中提取的值。像这样的东西
public static void testMethod() {
byte[] data = new byte[] {0x46, 0x24}; // 01000110 00100100
int mask = 0x663C; // 01100110 00111100
int x = readIntFromMaskedBytes(data, mask);
}
public static int readIntFromMaskedBytes(byte[] data, int mask) {
int result = 0;
// use the mask to extract the marks bits from each
// byte and shift them appropriately to form an int
return result;
}
我已经完成了我正在使用原始“手动”方法进行的项目,但由于这些事件的数量及其复杂性,我不满意它是否尽可能干净。我想提出一种更通用的方法来完成同样的事情。
不幸的是,当涉及到这种复杂的位移时,我仍然是一个新手,我希望有人可以就如何最好地实现这一点提供一些建议或建议。
Xela
注意 - 请原谅上面伪代码中的任何语法错误,它只是用作对用例的解释。
答案 0 :(得分:1)
实际上,我倾向于认为内联掩码和移位方法(如果实现比伪代码更干净)比尝试编写通用方法更好。对于经验丰富的低级位抨击代码开发人员来说,读取掩码和移位代码应该没有问题。您提出的通用方法的问题在于它的效率会大大降低......并且JIT编译器难以优化。
BTW,这就是我编写代码的方式。
// extract and assemble xxxx from yyyy
int w = ((0x003C & data[0]) >> 2) |
((0x0600 & data[0]) >> 6) |
((0x6000 & data[0]) >> 7);
修改强>
我仍然想了解如何编写这种通用方法,作为一种学习练习。
这样的事情:
public static int readIntFromMaskedBytes(int data, int mask) {
int result = 0;
int shift = 0;
while (mask != 0) {
if (mask & 1) {
result |= (data & 1) << shift++;
}
data >>>= 1;
mask >>>= 1;
}
}
正如您所看到的,这将需要多达32次循环迭代才能给出答案。就你的例子而言,我认为这种方法比原始版本慢大约10倍。