无论我如何折腾并转动字节和比特,我只是无法让这个工作。我理解endianess相当不错,而MSB(最重要的一点)在某种程度上。但我似乎无法将两者放在一起。
目前,我将数据放在普通的JAVA byte []数组中。位流内的符号使用32位little-endian最高至最低有效位打包进行编码。我需要在一个位读取器N位读取它,如:
public int read(int bits, boolean advanceReader)
当然要跟踪
private int byteOffset;
private int bitOffset;
问题是将值变为整数,我只能理解如何正确实现:(
编辑:我尝试使用这个Apache Licensed BitReader类添加了小端(我添加到readInt())支持(原始代码:https://raw.githubusercontent.com/jcodec/jcodec/master/src/main/java/org/jcodec/common/io/BitReader.java):
public class BitReader {
protected int deficit;
protected int curInt;
private ByteBuffer bb;
private int initPos;
public BitReader(ByteBuffer bb) {
this.bb = bb;
initPos = bb.position();
curInt = readInt();
deficit = 0;
}
public final int readInt() {
if (bb.remaining() >= 4) {
deficit -= 32;
final int b1 = bb.get() & 0xff;
final int b2 = bb.get() & 0xff;
final int b3 = bb.get() & 0xff;
final int b4 = bb.get() & 0xff;
if (bb.order() == ByteOrder.BIG_ENDIAN) {
return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
} else {
return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
}
} else {
return readIntSafe();
}
}
public int readNBit(int n) {
if (n > 32) {
throw new IllegalArgumentException("Can not read more then 32 bit");
}
int nn = n;
int ret = 0;
if (n + deficit > 31) {
ret |= (curInt >>> deficit);
n -= 32 - deficit;
ret <<= n;
deficit = 32;
curInt = readInt();
}
if (n != 0) {
ret |= curInt >>> (32 - n);
curInt <<= n;
deficit += n;
}
// for(--nn; nn >=0; nn--)
// System.out.print((ret >> nn) & 1);
// System.out.println();
return ret;
}
public int position() {
return ((bb.position() - initPos - 4) << 3) + deficit;
}
}
也许我在readNBit中遗漏了一些东西,它仍然像大端一样处理?结果就在附近,但不太正确。
一些数据:
阵列:
[0]字节64
[1]字节1
[2]字节-32
[3]字节1
[4]字节100
[5]字节20
[6]字节30
[7]字节3
[8]字节47
[9]字节-91
[10]字节52
[11]字节-12
[12]字节2
[13]字节-6
[14]字节11
[15]字节-24
[16]字节41
[17]字节98
[18]字节-124
[19]字节52
赤字= 21
位置(字节数组)= 12
读32位让我:-1510145665
显然应该是:-1510145696
byte[] array = {
64, 1, -32, 1,
100, 20, 30, 3,
47, -91, 52, -12,
2, -6, 11, -24,
41, 98, -124, 52
};
ByteBuffer bArray = ByteBuffer.wrap(array);
bArray.order(ByteOrder.LITTLE_ENDIAN);
BitReader bitReader = new BitReader(bArray);
bitReader.readNBit(32);
bitReader.readNBit(32);
bitReader.readNBit(21);
int luku = bitReader.readNBit(32);
Luku == -1510145665,我认为应该是-1510145696。
答案 0 :(得分:0)
47, -91, 52, -12 to little endian int => 11110100001101001010010100101111
2, -6, 11, -24 to little endian int => 11101000000010111111101000000010
消耗21位后,以下32位10100101111111010000000101111111
为十六进制0xA5FD017F
,十进制为2784821631
。
System.out.println(0xA5FD017F);
long l = 2784821631L;
System.out.println((int)l);
都会给你-1510145665。所以原始代码是正确的。
当您一次读取少于32位时,将输入字节数组视为小端的更改可能不是您想要的。您可能必须一次读取一个字节而不是使用现有的readInt()