2

简短的问题

有没有办法将两个字节读取为有符号整数?

详细信息和示例

给定 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

这些只是例子。会有更多字节,它们将代表正整数和负整数。

有没有办法将两个字节作为有符号整数读取并获得正确的结果?

提前致谢。

4

3 回答 3

2

在您的情况下,您可以&从高字节中删除按位:

int i = (byteArray[2] << 8) | (byteArray[3] & 0xff);

& 0xff正在撤消您想要的符号扩展。你仍然需要它的低字节。

补码符号扩展的工作方式如下:

  1. 如果设置了较小尺寸编号的最高有效位,

    //    v
        0b1000000_00000000
    
  2. 用 1 填充旧最重要位上方的新位:

    //    vvvvvvvv vvvvvvvv
        0b11111111_11111111_1000000_00000000
    

byte每当 a orshort转换为intor时, Java 都会自动执行此操作,而on along的目的是撤消自动符号扩展。& 0xFFbyte

如果您无权访问字节,则可以使用算术右移自己进行符号扩展:

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;
于 2018-06-22T15:11:20.260 回答
1

两个字节作为有符号整数:

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);
    }
}

(我将在此处粘贴我在您的问题下所做的评论):

改用a short,因为你的最左边int是0,所以它是一个正数。但是如果你使用 a short,那么你会得到你想要的负值,因为类型short只有 2 个字节,那么最左边的位将是 0xFF 中最左边的 1,使其成为负数。

于 2018-06-22T03:51:36.993 回答
0

科特林方式

        val low: UByte = bytes[3].toUByte()
        val high: UByte = bytes[4].toUByte()

        return (high.toInt() shl 8) or low.toInt()
于 2020-12-29T12:17:11.257 回答