将两个字节转换为 java 中的有符号整数
Convert two bytes to a signed integer in java
简答题
有没有办法将两个字节读取为有符号整数?
详细信息和示例
给定 java 中的两个字节,每个字节代表一个整数,我们可以通过简单地将它们转换为它们一起表示的 int 值:
byte[] byteArray = new byte[4];
byteArray[0] = 0x00;
byteArray[1] = 0x00;
byteArray[2] = .. //a byte representing an integer
byteArray[3] = .. //a byte representing an integer
int i = ((byteArray[2] & 0xff) << 8) | (byteArray[3] & 0xff);
当两位代表正整数时,它完美地工作。但是当两个整数都是负数时它会失败。
例如当:
byteArray[2] = 0xff; // -1
byteArray[3] = 0xf9; // -7
我得到:
i = 65529;
这是不正确的。它应该只是 -8 即 0xf8.
我尝试使用 ByteBuffer:
byte[] array = new byte[4];
array[0] = 0x00;
array[1] = 0x00;
array[2] = 0xff;
array[3] = 0xf9;
ByteBuffer buffer = ByteBuffer.wrap(array);
int i = buffer.getInt();
没有成功。得到相同的结果:
i = 65529
这些只是例子。将有更多字节,它们将代表正整数和负整数。
有没有办法读取两个字节作为有符号整数并得到正确的结果?
提前致谢。
两个字节作为有符号整数:
public class MyClass {
public static void main(String args[]) {
byte h = (byte)0xff;
byte l = (byte)0xf9;
int i = (short) ((h << 8) | l);
System.out.println(i);
}
}
(我会把我在你的问题下的评论贴在这里):
改用short
,因为你的int
最左边的位是0,所以是正数。但是如果你使用short
,那么你会得到你想要的负值,因为short
类型只有2个字节,那么最左边的位将是0xFF中最左边的1,使其成为负数。
在你的情况下,你可以从高字节中删除按位&
:
int i = (byteArray[2] << 8) | (byteArray[3] & 0xff);
& 0xff
正在撤消您想要的符号扩展。 You still need it on the low byte.
补码扩展的工作原理如下:
如果设置了较小尺寸数字的最高有效位,
// v
0b1000000_00000000
用1s填充旧最高有效位上方的新位:
// vvvvvvvv vvvvvvvv
0b11111111_11111111_1000000_00000000
Java 会在任何时候将 byte
或 short
转换为 int
或 long
时自动执行此操作,而 [=23= 的目的] 在 byte
上是撤消自动符号扩展。
如果您无法访问字节,您可以使用算术右移自行进行符号扩展:
i = (i << 16) >> 16;
或转换为 short
:
i = (short) i;
或各种if
测试如:
if ((i & 0x80_00) != 0) // Is the MSB of the high byte set?
i |= 0xFF_FF_00_00; // Fill the rest with 1s.
并且:
if (i > 32767)
i -= 65536;
kotlin 方式
val low: UByte = bytes[3].toUByte()
val high: UByte = bytes[4].toUByte()
return (high.toInt() shl 8) or low.toInt()
简答题
有没有办法将两个字节读取为有符号整数?
详细信息和示例
给定 java 中的两个字节,每个字节代表一个整数,我们可以通过简单地将它们转换为它们一起表示的 int 值:
byte[] byteArray = new byte[4];
byteArray[0] = 0x00;
byteArray[1] = 0x00;
byteArray[2] = .. //a byte representing an integer
byteArray[3] = .. //a byte representing an integer
int i = ((byteArray[2] & 0xff) << 8) | (byteArray[3] & 0xff);
当两位代表正整数时,它完美地工作。但是当两个整数都是负数时它会失败。 例如当:
byteArray[2] = 0xff; // -1
byteArray[3] = 0xf9; // -7
我得到:
i = 65529;
这是不正确的。它应该只是 -8 即 0xf8.
我尝试使用 ByteBuffer:
byte[] array = new byte[4];
array[0] = 0x00;
array[1] = 0x00;
array[2] = 0xff;
array[3] = 0xf9;
ByteBuffer buffer = ByteBuffer.wrap(array);
int i = buffer.getInt();
没有成功。得到相同的结果:
i = 65529
这些只是例子。将有更多字节,它们将代表正整数和负整数。
有没有办法读取两个字节作为有符号整数并得到正确的结果?
提前致谢。
两个字节作为有符号整数:
public class MyClass {
public static void main(String args[]) {
byte h = (byte)0xff;
byte l = (byte)0xf9;
int i = (short) ((h << 8) | l);
System.out.println(i);
}
}
(我会把我在你的问题下的评论贴在这里):
改用short
,因为你的int
最左边的位是0,所以是正数。但是如果你使用short
,那么你会得到你想要的负值,因为short
类型只有2个字节,那么最左边的位将是0xFF中最左边的1,使其成为负数。
在你的情况下,你可以从高字节中删除按位&
:
int i = (byteArray[2] << 8) | (byteArray[3] & 0xff);
& 0xff
正在撤消您想要的符号扩展。 You still need it on the low byte.
补码扩展的工作原理如下:
如果设置了较小尺寸数字的最高有效位,
// v 0b1000000_00000000
用1s填充旧最高有效位上方的新位:
// vvvvvvvv vvvvvvvv 0b11111111_11111111_1000000_00000000
Java 会在任何时候将 byte
或 short
转换为 int
或 long
时自动执行此操作,而 [=23= 的目的] 在 byte
上是撤消自动符号扩展。
如果您无法访问字节,您可以使用算术右移自行进行符号扩展:
i = (i << 16) >> 16;
或转换为 short
:
i = (short) i;
或各种if
测试如:
if ((i & 0x80_00) != 0) // Is the MSB of the high byte set?
i |= 0xFF_FF_00_00; // Fill the rest with 1s.
并且:
if (i > 32767)
i -= 65536;
kotlin 方式
val low: UByte = bytes[3].toUByte()
val high: UByte = bytes[4].toUByte()
return (high.toInt() shl 8) or low.toInt()