【问题标题】:Can I simplify reading a short from binary data我可以简化从二进制数据中读取短信息吗
【发布时间】:2015-12-14 08:38:03
【问题描述】:

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

给定两个字节 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 已签名!无论如何,我怀疑这里的错误在于Hex 类;显示所有.asHex()方法的代码

标签: java io nio bytebuffer


【解决方案1】:

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

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

或者,如果您使用 Java 8:

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

这基本上会从int 中删除所有不属于short 的位。但这不会减轻您仔细检查您期望无符号值的位置以及如何在各自的上下文中处理(自然)有符号值的责任。

【讨论】:

    【解决方案2】:

    您确实得到了相同的值。当您将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;
    

    【讨论】:

    • 好的,我现在在 Java 中对它的理解更好,short 已签名,因此它将显示的最大值为 32,767,因此 0xffFe (65534) 的值太大,无法按照我在 Short 中的要求显示,但我不能使用 ByteBuffers getInteger() 因为我只想读取两个字节而不是四个。所以我不能将它分配给整数,问题是如果与其他值(例如枚举)进行比较,所有文字都必须转换为short,因为默认情况下假定为int,或者执行& 0xff来分配给int,不确定whihc是最好的真的
    • @PaulTaylor 我编辑添加了一种在将 short 读入 int 时将其视为未签名的方法。
    【解决方案3】:

    我的假设是,在您的 Hex 类中,您有一个 .asHex() 方法,该方法采用 short 作为参数,其作用类似于:

    int value = (int) argument;
    

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

    如果您想将其转换为无符号值,则必须将其屏蔽,如下所示:

    int value = (int) argument & 0xffff;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-25
      • 1970-01-01
      • 1970-01-01
      • 2017-07-08
      • 2013-09-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多