使用按位运算符将 byte 转换为 int

2023-12-22

我正在用 Java 记录一些代码。目标是阅读并处理OSRM文件 http://project-osrm.org/这是一个包含十六进制代码的文件。

流程如下:读入某个字节到aByteBuffer用一个FileChannel。缓冲区填满后,将每个字节转换为有符号整数。这是使用按位完成的&运算符和有符号左移运算符<<,看起来像这样:

return  (0x000000ff & (bb.get() << 0)) |
        (0x0000ff00 & (bb.get() << 8)) |
        (0x00ff0000 & (bb.get() << 16)) |
        (0xff000000 & (bb.get() << 24));

Where bb当然是ByteBuffer.

我完全不知道这段代码是如何以及为什么工作的,我用谷歌搜索了一下,我发现的最接近的是以下堆栈溢出问题:将 Java 方法转换为 C#:使用位移运算符将字节转换为整数 https://stackoverflow.com/questions/6920993/converting-java-method-to-c-converting-bytes-to-integers-with-bit-shift-operat.

尽管如此,我还是不知道,我想知道是否有人可以帮助我找出这个代码片段。


这从底层字节缓冲区读取四个字节并将它们拼接在一起形成一个int像这样的值:

                        11111111 (first byte read)
                22222222         (second byte read)
        33333333                 (third byte read)
44444444                         (fourth byte read)

为了实现这一点,对所有子结果执行按位或运算,其中每个子结果准备上图中的一行。例如,第三行准备为

(0x00ff0000 & (bb.get() << 16))

它执行以下操作:

  1. 读取字节:

    xxxxxxxx
    
  2. 扩大byte进入一个int:

    000000000000000000000000xxxxxxxx        
    
  3. 将位左移 16 个槽:

    00000000xxxxxxxx0000000000000000
    
  4. 最后,将其推入 AND 掩码,该掩码仅允许x位通过。这是需要的,因为byte已签名,因此转换为int实际上可能会导致以下结果:

    111111111111111111111111xxxxxxxx
    

如果执行常量 AND 掩码,代码可能会更简单before转移:

(bb.get() & 0xFF) << 16

这实际上是 Java 在这些位操作中的标准习惯用法。


虽然不是您所问问题的答案,但使用提供的 API 肯定是首选(getInt方法)。您的字节顺序是小尾数,所以您只需要设置它:

bb.order(ByteOrder.LITTLE_ENDIAN);

作为参考,这是 JDK 对相同代码的实现:

static private int makeInt(byte b3, byte b2, byte b1, byte b0) {
    return (((b3       ) << 24) |
            ((b2 & 0xff) << 16) |
            ((b1 & 0xff) <<  8) |
            ((b0 & 0xff)      ));
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用按位运算符将 byte 转换为 int 的相关文章

随机推荐