使用按位运算符将 byte 转换为 int
convert byte to int using bit wise opertators
我正在 Java 中记录一些代码。在我问我的问题之前,我会给你们一些背景信息。目标是读取和处理 orsm file 这是一个包含十六进制代码的文件。
流程如下:使用FileChannel
将一些字节读入ByteBuffer
。缓冲区填满后,将每个字节转换为有符号整数。这是使用按位 &
运算符和带符号的左移运算符 <<
完成的,看起来像这样:
return (0x000000ff & (bb.get() << 0)) |
(0x0000ff00 & (bb.get() << 8)) |
(0x00ff0000 & (bb.get() << 16)) |
(0xff000000 & (bb.get() << 24));
其中bb
当然是ByteBuffer
。我完全不知道这段代码如何工作以及为什么工作,我用谷歌搜索了一下,发现最接近的是以下 Stack Overflow 问题:Converting java method to C#: converting bytes to integers with bit shift operators。我仍然一无所知,我想知道是否有人可以帮助我找出这段代码?
这从底层字节缓冲区读取四个字节并将它们拼接成一个 int
值,如下所示:
11111111 (first byte read)
22222222 (second byte read)
33333333 (third byte read)
44444444 (fourth byte read)
为此,对所有子结果执行按位或运算,其中每个子结果在上图中准备一行。比如第三行准备为
(0x00ff0000 & (bb.get() << 16))
执行以下操作:
读取字节:
xxxxxxxx
将 byte
扩展为 int
:
000000000000000000000000xxxxxxxx
将位向左移动 16 个槽位:
00000000xxxxxxxx0000000000000000
最后,将其推入一个 AND 掩码,该掩码仅允许 x
位通过。这是必需的,因为 byte
已签名,因此转换为 int
实际上可能会导致以下结果:
111111111111111111111111xxxxxxxx
如果在 移位之前执行常量与掩码,代码可能会更简单:
(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) ));
}
基本上,它读取四个字节,每个字节是八位,然后将它们组合成一个32位的整数。它通过将每个连续字节向左额外移动 8 位来实现这一点,因此读取的第一个字节被放置在整数 (0-7) 的最后(最低位)8 位中;下一个字节进入下一个 8 位 (15-8),等等
虽然使用 ByteBuffer 的实际功能来执行此操作会容易得多:
bb.order(ByteOrder.LITTLE_ENDIAN); // Called once on the buffer
int intFromNextFourBytes = bb.getInt(); // Read the same value as your code.
我正在 Java 中记录一些代码。在我问我的问题之前,我会给你们一些背景信息。目标是读取和处理 orsm file 这是一个包含十六进制代码的文件。
流程如下:使用FileChannel
将一些字节读入ByteBuffer
。缓冲区填满后,将每个字节转换为有符号整数。这是使用按位 &
运算符和带符号的左移运算符 <<
完成的,看起来像这样:
return (0x000000ff & (bb.get() << 0)) |
(0x0000ff00 & (bb.get() << 8)) |
(0x00ff0000 & (bb.get() << 16)) |
(0xff000000 & (bb.get() << 24));
其中bb
当然是ByteBuffer
。我完全不知道这段代码如何工作以及为什么工作,我用谷歌搜索了一下,发现最接近的是以下 Stack Overflow 问题:Converting java method to C#: converting bytes to integers with bit shift operators。我仍然一无所知,我想知道是否有人可以帮助我找出这段代码?
这从底层字节缓冲区读取四个字节并将它们拼接成一个 int
值,如下所示:
11111111 (first byte read)
22222222 (second byte read)
33333333 (third byte read)
44444444 (fourth byte read)
为此,对所有子结果执行按位或运算,其中每个子结果在上图中准备一行。比如第三行准备为
(0x00ff0000 & (bb.get() << 16))
执行以下操作:
读取字节:
xxxxxxxx
将
byte
扩展为int
:000000000000000000000000xxxxxxxx
将位向左移动 16 个槽位:
00000000xxxxxxxx0000000000000000
最后,将其推入一个 AND 掩码,该掩码仅允许
x
位通过。这是必需的,因为byte
已签名,因此转换为int
实际上可能会导致以下结果:111111111111111111111111xxxxxxxx
如果在 移位之前执行常量与掩码,代码可能会更简单:
(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) ));
}
基本上,它读取四个字节,每个字节是八位,然后将它们组合成一个32位的整数。它通过将每个连续字节向左额外移动 8 位来实现这一点,因此读取的第一个字节被放置在整数 (0-7) 的最后(最低位)8 位中;下一个字节进入下一个 8 位 (15-8),等等
虽然使用 ByteBuffer 的实际功能来执行此操作会容易得多:
bb.order(ByteOrder.LITTLE_ENDIAN); // Called once on the buffer
int intFromNextFourBytes = bb.getInt(); // Read the same value as your code.