我可以简化从二进制数据中读取短片吗
Can I simplify reading a short from binary data
我正在尝试简化一些用于解码文件中数据的代码,并且我已经编写了一个测试用例来说明这个问题。
给定两个字节 0xFe
和 0xFF
我希望将其读作 0xFFFE
(65534),
现有代码
headerBuffer.get() & 0xff + (headerBuffer.get() & 0xff) * 256
我想,如果我将缓冲区字节顺序设为小端,我可以通过短读来获得相同的结果。但是我没有得到相同的结果,为什么不呢?
headerBuffer.getShort();
public void testReadingOfShort() {
ByteBuffer headerBuffer = ByteBuffer.allocate(2);
headerBuffer.order(ByteOrder.LITTLE_ENDIAN);
headerBuffer.put((byte) 0xFE);
headerBuffer.put((byte)0xFF);
headerBuffer.position(0);
int format = headerBuffer.get() & 0xff + (headerBuffer.get() & 0xff) * 256;
headerBuffer.position(0);
int formatNew = headerBuffer.getShort();
System.out.println("Format:"+format+"("+ Hex.asHex(format)+")"+":FormatNew:"
+formatNew+"("+Hex.asHex(formatNew)+")");
}
输出
Format:65534(0xfffe):FormatNew:-2(0xfffffffffffffffe)
你确实得到了同样的价值。当您在此行将 short
分配给 int
时会出现问题:
int formatNew = headerBuffer.getShort();
执行此操作时,Java 执行 符号扩展 以确保 short
中的数值转换为相同的数值int
。在您的情况下,即 -2.
-2表示为short
是0xFFFE
,而int
表示是0xFFFFFFFE
。换句话说,short
的符号位被复制到 int
的附加高位。
您可以通过不将 short
分配给 int
来解决此问题。您还需要确保您的 Hex.asHex
对 short
有适当的重载,否则当 formatNew
作为参数传递时会发生相同的转换。
或者,如果您想将 short
的值视为无符号,并将其分配给 int
,您可以使用 0xFFFF
屏蔽结果,如下所示:
int formatNew = headerBuffer.getShort() & 0xFFFF;
我的假设是,在您的 Hex
class 中,您有一个 .asHex()
方法以 short
作为参数,它执行如下操作:
int value = (int) argument;
运气不好。如果您 "upcast" 从一种整数类型到另一种整数类型,则符号位(如果存在) 是 携带的。这意味着如果你尝试将 short 0xfffe 转换为 int,你将不会以 0x0000fffe 结束,而是...... 0xfffffffe。因此你的结果。
如果您想将其转换为无符号值,则必须将其屏蔽,如下所示:
int value = (int) argument & 0xffff;
您可以简单地获得所需的值
int formatNew = headerBuffer.getShort() & 0xFFFF;
或者,如果您使用 Java 8:
int formatNew = Short.toUnsignedInt(headerBuffer.getShort());
这基本上会删除 int
中不属于 short
的所有位。但这并不能免除您仔细检查期望无符号值的位置以及如何在相应上下文中处理(自然)带符号值的责任。
我正在尝试简化一些用于解码文件中数据的代码,并且我已经编写了一个测试用例来说明这个问题。
给定两个字节 0xFe
和 0xFF
我希望将其读作 0xFFFE
(65534),
现有代码
headerBuffer.get() & 0xff + (headerBuffer.get() & 0xff) * 256
我想,如果我将缓冲区字节顺序设为小端,我可以通过短读来获得相同的结果。但是我没有得到相同的结果,为什么不呢?
headerBuffer.getShort();
public void testReadingOfShort() {
ByteBuffer headerBuffer = ByteBuffer.allocate(2);
headerBuffer.order(ByteOrder.LITTLE_ENDIAN);
headerBuffer.put((byte) 0xFE);
headerBuffer.put((byte)0xFF);
headerBuffer.position(0);
int format = headerBuffer.get() & 0xff + (headerBuffer.get() & 0xff) * 256;
headerBuffer.position(0);
int formatNew = headerBuffer.getShort();
System.out.println("Format:"+format+"("+ Hex.asHex(format)+")"+":FormatNew:"
+formatNew+"("+Hex.asHex(formatNew)+")");
}
输出
Format:65534(0xfffe):FormatNew:-2(0xfffffffffffffffe)
你确实得到了同样的价值。当您在此行将 short
分配给 int
时会出现问题:
int formatNew = headerBuffer.getShort();
执行此操作时,Java 执行 符号扩展 以确保 short
中的数值转换为相同的数值int
。在您的情况下,即 -2.
-2表示为short
是0xFFFE
,而int
表示是0xFFFFFFFE
。换句话说,short
的符号位被复制到 int
的附加高位。
您可以通过不将 short
分配给 int
来解决此问题。您还需要确保您的 Hex.asHex
对 short
有适当的重载,否则当 formatNew
作为参数传递时会发生相同的转换。
或者,如果您想将 short
的值视为无符号,并将其分配给 int
,您可以使用 0xFFFF
屏蔽结果,如下所示:
int formatNew = headerBuffer.getShort() & 0xFFFF;
我的假设是,在您的 Hex
class 中,您有一个 .asHex()
方法以 short
作为参数,它执行如下操作:
int value = (int) argument;
运气不好。如果您 "upcast" 从一种整数类型到另一种整数类型,则符号位(如果存在) 是 携带的。这意味着如果你尝试将 short 0xfffe 转换为 int,你将不会以 0x0000fffe 结束,而是...... 0xfffffffe。因此你的结果。
如果您想将其转换为无符号值,则必须将其屏蔽,如下所示:
int value = (int) argument & 0xffff;
您可以简单地获得所需的值
int formatNew = headerBuffer.getShort() & 0xFFFF;
或者,如果您使用 Java 8:
int formatNew = Short.toUnsignedInt(headerBuffer.getShort());
这基本上会删除 int
中不属于 short
的所有位。但这并不能免除您仔细检查期望无符号值的位置以及如何在相应上下文中处理(自然)带符号值的责任。