【问题标题】:Java Byte[] to int (Big Endian) using << WeirdnessJava Byte[] 到 int (Big Endian) 使用 << Weirdness
【发布时间】:2014-06-06 04:43:16
【问题描述】:

假设我们有以下字节[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 已经“异或”到了正确的位置。为什么会这样?

【问题讨论】:

  • 数字不是用 Java 签名的吗?
  • 那些不是有效的字节值。请给我们一个最小的工作示例。
  • @AnubianNoob 是的,Java 已签名......但如果我用十六进制打印它应该没关系吧?
  • @SotiriosDelimanolis 你是什么意思他们不是有效的字节值? 0x44a48ac6 = 1151634118。
  • @ChaosXDemon 0xA4 不是有效的byte 值。 Java 中的bytes 的范围是 -128 到 127(-0x80 到 0x7F)

标签: java int byte endianness


【解决方案1】:

bytes 在 Java 中的范围从 -128 (-0x80) 到 127 (0x7F)。 164 (0xA4) 不是有效值,但“A4”是您通过打印 -92 (-0x5C) 得到的结果,就像它是无符号的一样。

将 -0x5C 转换为 int 也会得到 -0x0000005C。 -0x0000005C,打印为无符号,为0xFFFFFFA4。

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

0xFFFFFFA4 &lt;&lt; 16 给出0xFFA400000x44000000 | 0xFFA40000 给出0xFFA40000 - 这就是你得到这个结果的方式。

修复很简单 - 使用 ((int)raw[i] &amp; 0xFF) 代替 raw[i],或者只使用 (raw[i] &amp; 0xFF),因为到 int 的转换是隐式的。

另外,与那个问题无关,(result &lt;&lt; 4) 应该是(result &lt;&lt; 8)。否则,您将计算 0x44000 | 0xA400 | 0x8A0 | 0xC6 而不是 0x44000000 | 0xA40000 | 0x8A00 | 0xC6

【讨论】:

  • 感谢您的详细解释。现在说得通了!
【解决方案2】:

在实践中,做

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

有开销,但它如此简单。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-01
    • 2019-06-30
    • 1970-01-01
    • 2018-05-15
    • 2022-06-10
    • 2011-10-06
    • 1970-01-01
    相关资源
    最近更新 更多