我正在从串口读取一个长度为 133 字节的数据包,其中最后两个字节包含 CRC 值。我使用 Java 将这两个字节值组合成一个短整型数。
以下是我的代码:
short high = (-48 & 0x00ff);
short low = 80;
short c = (short) ((high << 8) + low);
但是我没有得到正确的结果。这是因为使用了有符号的值吗? 我该如何解决这个问题?
我正在从串口读取一个长度为 133 字节的数据包,其中最后两个字节包含 CRC 值。我使用 Java 将这两个字节值组合成一个短整型数。
以下是我的代码:
short high = (-48 & 0x00ff);
short low = 80;
short c = (short) ((high << 8) + low);
但是我没有得到正确的结果。这是因为使用了有符号的值吗? 我该如何解决这个问题?
记住,如果你对位移操作不太熟悉,就不必自己绞尽脑汁了。你可以使用 ByteBuffer 来帮助你:
ByteBuffer bb = ByteBuffer.allocate(2);
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.put(firstByte);
bb.put(secondByte);
short shortVal = bb.getShort(0);
反过来,您可以先输入一个 short ,然后再提取字节。
顺便说一下,位运算会自动将操作数提升至至少 int 的宽度。实际上,并不存在“不允许将一个字节左移超过7位”之类的说法或其他似乎正在传播的谣言。
在Java中,当将流中的字节值转换为数字值时,必须非常小心地处理符号扩展。对于负数(来自(无符号)128-255的值),存在一个陷阱。
尝试这个方法(如果hi和lo是任何Java整数类型,则可行):
short val=(short)(((hi & 0xFF) << 8) | (lo & 0xFF));
我发现在这些情况下使用括号更加明确。
当尝试连接字节时会发生这种情况(非常微妙)
byte b1 = (byte) 0xAD;
byte b2 = (byte) 0xCA;
short s = (short) (b1<<8 | b2);
以上代码的输出结果是0xFFCA,这是不正确的。这是因为b2是负数(byte 类型是有符号的!),这意味着当它被转换为 int 类型进行位或运算时,它将被填充为 0xF!
因此,您必须记得屏蔽填充的字节,以确保它们肯定为零:
short s = (short) (b1<<8 | b2 & 0xFF);
short high=(-48 & 0x00ff);
short low=80;
int c= ((high & 0xFF) << 8) | (low & 0xFF);
short
类型可以表示-32768到32767之间的值。53328无法很好地存储在short中,使用int
代替它,因为它允许您存储无符号值,高达~109。因此,请不要将表达式转换为short,因为这会给您带来有符号值。
& 0x00FF
来将无符号字节转换为短整型。例如,将0x87设置成短整型时,得到的结果是-121,而不是预期的135。 - wrapperapps您可以以更易读且更优雅的方式将2个字节转换为short。
short s = ByteBuffer.wrap(new byte[]{0x01, 0x02}).getShort();
// now s equals 258 = 256 + 2
这对我有效
short temp = ;
result[0] = (byte) ((temp >>> 8) & 0xFF);
result[1] = (byte)((temp) & 0xFF);