使用位操作符将字节转换为int

jor*_*rne 0 java int byte bytebuffer bit-manipulation

我在java中记录了一些代码.在我问我的问题之前,我会给你们一些背景信息.目标是读取和处理orsm文件,该文件是包含十六进制代码的文件.

流程如下:使用FileChannel将somme字节读入ByteBuffer.填充缓冲区后,将每个字节转换为有符号整数.这是使用移位运算符完成的,如下所示:

return  (0x000000ff & (bb.get() << 0)) |
        (0x0000ff00 & (bb.get() << 8)) |
        (0x00ff0000 & (bb.get() << 16)) |
        (0xff000000 & (bb.get() << 24));
Run Code Online (Sandbox Code Playgroud)

其中bb属于Bytebuffer.我完全不知道这段代码是如何以及为什么有效的,我搜索了一个出价,我找到的关闭的东西是这个旧的stackoverflow主题.我仍然没有任何线索,我想知道你是否可以帮助我解决这个代码剪断?

Mar*_*nik 6

这将从底层字节缓冲区中读取四个字节,并将它们拼接成一个int如下所示的值:

                        11111111 (first byte read)
                22222222         (second byte read)
        33333333                 (third byte read)
44444444                         (fourth byte read)
Run Code Online (Sandbox Code Playgroud)

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

(0x00ff0000 & (bb.get() << 16))
Run Code Online (Sandbox Code Playgroud)

执行以下操作:

  1. 读取字节:

    xxxxxxxx
    
    Run Code Online (Sandbox Code Playgroud)
  2. 扩展byteint:

    000000000000000000000000xxxxxxxx        
    
    Run Code Online (Sandbox Code Playgroud)
  3. 将位向左移位16个插槽:

    00000000xxxxxxxx0000000000000000
    
    Run Code Online (Sandbox Code Playgroud)
  4. 最后,通过一个AND掩码推送它,它只允许x位通过.这是必需的,因为byte已签名,因此转换为int实际可能导致以下结果:

    111111111111111111111111xxxxxxxx
    
    Run Code Online (Sandbox Code Playgroud)

如果移位之前执行了常量的AND-mask,代码可能会更简单:

(bb.get() & 0xFF) << 16
Run Code Online (Sandbox Code Playgroud)

这实际上是Java在这些bit-twiddling操作中的标准习惯用法.


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

bb.order(ByteOrder.LITTLE_ENDIAN);
Run Code Online (Sandbox Code Playgroud)

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

static private int makeInt(byte b3, byte b2, byte b1, byte b0) {
    return (((b3       ) << 24) |
            ((b2 & 0xff) << 16) |
            ((b1 & 0xff) <<  8) |
            ((b0 & 0xff)      ));
}
Run Code Online (Sandbox Code Playgroud)