【问题标题】:How to convert a uint16 stored as a little endian byte array to an int?如何将存储为小端字节数组的 uint16 转换为 int?
【发布时间】:2020-04-20 16:35:03
【问题描述】:

我收到一些数据,它是一个代表 uint16 的小端字节数组,但我想将其存储在 int 中。我已将此数据包装到 ByteBuffer 中,因此我可以调用 ByteBuffer.get() 以获取下一个字节,但我不确定如何将这 2 个字节从 uint16 转换为 int

    byte[] data = //From UDP socket
    ByteBuffer bb = ByteBuffer.wrap(data);
    bb = bb.order(ByteOrder.LITTLE_ENDIAN);
    while(bb.hasRemaining()){
        int n = //What goes here?
    }

感谢您的帮助:)

【问题讨论】:

    标签: java arrays type-conversion integer unsigned-integer


    【解决方案1】:

    在我看来,主要的复杂性在于如何在 Java 中表示 uint16。我建议使用 Java int 或 Java long,因为至少 16 位与 uint16 中的含义相同(但不是 Java short:它有 16 位,但有符号)。

    1) 如果您只收到 uint16,没有字符,没有其他类型,那么最简单的方法就是跟随。将 16 位读入 Java short,然后将其转换为 int

    byte[] data = //From UDP socket
    ByteBuffer bb = ByteBuffer.wrap(data);
    bb = bb.order(ByteOrder.LITTLE_ENDIAN);
    
    while(bb.hasRemaining()){
        short s = bb.getShort();
        int n = 0xFFFF & s;
        ...
    }
    

    2) 如果您不仅收到 uint16,还收到一些其他类型,例如 chars,那么您可以从 2 个字节构造值:

    byte[] data = //From UDP socket
    ByteBuffer bb = ByteBuffer.wrap(data);
    
    while(bb.hasRemaining()) {
        if (consider next bytes as uint16) {
            byte b1 = bb.get();
            byte b2 = bb.get();
            int i1 = 0xFF & b1; // Consider b1 as int, not the same as "(int) b1"
            int i2 = 0xFF & b2; // Consider b2 as int, not the same as "(int) b2"
            int n = b2 * 256 + b1;
            ...
        } else {
            // Read next bytes as char or something other
        }
    }
    

    【讨论】:

      【解决方案2】:

      ByteBuffer.wrap() 方法将数组转换为 HeapByteBuffer 类,其偏移量为 0,长度等于被包装的数组长度。您可以使用 bb.getShort(i) 方法访问两个字节,但这会在您想要无符号的地方返回负数。

      请注意,缓冲区的“endiness”仅在您调用诸如getShort() 之类的方法时才相关。如果您按需要的顺序访问字节,则缓冲区设置并不重要。

      按照与getShort() 方法类似的方法获取数据。以下是 Bits 类的元素:

      static short getShort(ByteBuffer bb, int bi, boolean bigEndian) {
          return bigEndian ? getShortB(bb, bi) : getShortL(bb, bi);
      }
      
      static short getShortL(ByteBuffer bb, int bi) {
          return makeShort(bb._get(bi + 1),
                           bb._get(bi    ));
      }
      
      static short getShortB(ByteBuffer bb, int bi) {
          return makeShort(bb._get(bi    ),
                           bb._get(bi + 1));
      }
      
      static private short makeShort(byte b1, byte b0) {
          return (short)((b1 << 8) | (b0 & 0xff));
      }
      

      所以你的例子可能是这样的

      public static void main(String[] args) {
      
          Long rawData = 0x01F2030405F60708L;
          byte[] x = new byte[8];
          ByteBuffer buf=ByteBuffer.allocate(8);
          buf.putLong(rawData);
          buf.position(0);
          buf.get(x);
          for (byte xi : x)
              System.out.printf("%02X, ", xi); 
          System.out.println(""); 
      
          byte[] data = x;//From UDP socket
          ByteBuffer bb = ByteBuffer.wrap(data);
          for (int i=0; i<data.length-1; i += 2) 
          {
              int n = ((bb.get(i+1) & 0xff) << 8) | (bb.get(i));
              System.out.printf("Hex: %04X int value: %d%n", n, n);
          }
      }
      

      或者,使用 getShort 并设置缓冲区的顺序

      public static void main(String[] args) {
      
          Long rawData = 0x01F2030405F60708L;
          byte[] x = new byte[8];
          ByteBuffer buf=ByteBuffer.allocate(8);
          buf.putLong(rawData);
          buf.position(0);
          buf.get(x);
          for (byte xi : x)
              System.out.printf("%02X, ", xi); 
          System.out.println(""); 
      
          byte[] data = x;//From UDP socket
          ByteBuffer bb = ByteBuffer.wrap(data);
          bb.order(ByteOrder.LITTLE_ENDIAN); // Required to use getShort()
          bb.position(0);
          while(bb.hasRemaining()) 
          {
              int n = bb.getShort() & 0xFFFF;
              System.out.printf("Hex: %04X int value: %d%n", n, n);
          }
      }
      

      两种解决方案都提供以下输出:

      01, F2, 03, 04, 05, F6, 07, 08, 
      Hex: F201 int value: 61953
      Hex: 0403 int value: 1027
      Hex: F605 int value: 62981
      Hex: 0807 int value: 2055
      

      【讨论】:

        猜你喜欢
        • 2020-06-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-20
        • 1970-01-01
        • 1970-01-01
        • 2022-12-06
        相关资源
        最近更新 更多