Java Byte []到int(Big Endian)使用<<怪事

时间:2014-06-06 04:43:16

标签: java int byte endianness

假设我们有以下字节[4]:

44 a4 8a c6

以下代码出现了什么问题:

public static int asIntBigEndian(byte[] raw, int offset){
int result = 0;
for(int i=offset; i<offset+4; ++i){
    result = (result << 4) | raw[i]; 
}
return result;
}

调用asIntBigEndian(raw,0)的结果是:

ff ff ff e6

我注意到的是,如果我要读取第一个字节并将其打印出来,我会得到:

44

如果我这样做,我会得到相同的结果:

System.out.println(Integer.toHexString(raw[0] << 24));

0x44000000

所以,如果我要继续逻辑......

System.out.println(Integer.toHexString( (raw[0] << 24)|(raw[1] << 16) );

0xffa40000

基本上第一个字节变为0xff而第二个字节0xa4变为&#34; xor&#34;到正确的位置。为什么会这样?

2 个答案:

答案 0 :(得分:3)

Java中的

byte的范围是-128(-0x80)到127(0x7F)。 164(0xA4)不是有效值,但是“A4”是打印-92(-0x5C)所得到的,就好像它是无符号的一样。

将-0x5C转换为int也会给出-0x0000005C。打印为无符号的-0x0000005C为0xFFFFFFA4。

考虑它的另一种可能更简单的方法是将所有值视为无符号,但将转换视为符号扩展 - 其中顶部位被复制到所有新位中。如果你这样想,0xA4是一个有效字节,(int)0xA4是0xFFFFFFA4。同样的结果,更简单的思考过程,但在Java中思考数字是一种不太正确的方式(并不是它有所作为)。

0xFFFFFFA4 << 16提供0xFFA400000x44000000 | 0xFFA40000提供0xFFA40000 - 这就是您获得该结果的方式。

修复很简单 - 而不是raw[i],使用((int)raw[i] & 0xFF),或只是(raw[i] & 0xFF),因为转换为int是隐含的。

此外,与该问题无关,(result << 4)应为(result << 8)。否则,您计算0x44000 | 0xA400 | 0x8A0 | 0xC6而不是0x44000000 | 0xA40000 | 0x8A00 | 0xC6

答案 1 :(得分:0)

在实践中,做

public static int asIntBigEndian(byte[] raw, int offset){
    ByteBuffer buffer = ByteBuffer.wrap(raw, offset, 4);
    buffer.order(ByteOrder.BIG_ENDIAN);
    return buffer.getInt();
}

有开销,但 很容易。

就此而言,在您的调用代码中,ByteBuffer可能会为您提供更好的服务。