我可以简化二进制数据的读取

时间:2015-09-17 13:01:06

标签: java io nio bytebuffer

我试图简化一些用于解码文件中数据的代码,并且我已经编写了一个测试用例来说明问题。

给定0xFe0xFF两个字节,我希望将其读作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)

3 个答案:

答案 0 :(得分:3)

你得到的价值相同。将short分配到此行的int时会出现问题:

int formatNew = headerBuffer.getShort();

执行此操作时,Java会执行签名扩展,以确保short中的数值转换为int中的相同数值。在你的情况下,那是-2。

-2作为short的表示形式为0xFFFE,而int表示形式为0xFFFFFFFE。换句话说,short的符号位被复制到int的附加高位。

您可以通过不将short分配给int来解决此问题。您还需要确保Hex.asHexshort有适当的重载,否则当formatNew作为参数传递时,会发生相同的转换。

或者,如果您希望将short的值视为未签名,并将其分配给int,则可以使用0xFFFF屏蔽结果,如下所示:< / p>

int formatNew = headerBuffer.getShort() & 0xFFFF;

答案 1 :(得分:0)

我的假设是,在Hex课程中,您使用.asHex()方法将short作为参数,其中包含以下内容:

int value = (int) argument;

运气好。如果您从一个整数类型“向上转换”到另一个整数类型,则符号位(如果存在) 被携带。这意味着如果你尝试将短0xfffe转换为int,你将不会得到0x0000fffe但是...... 0xfffffffe。因此你的结果。

如果你想把它作为无符号值投射,你必须掩盖它,如下所示:

int value = (int) argument & 0xffff;

答案 2 :(得分:0)

您可以简单地获得所需的值

int formatNew = headerBuffer.getShort() & 0xFFFF;

或者,如果您使用Java 8:

int formatNew = Short.toUnsignedInt(headerBuffer.getShort());

这将基本上丢弃int中不属于short的所有位。但是,它不会减轻您的责任,即仔细检查您希望无符号值的位置,以及如何在相应的上下文中处理(自然)签名值。