繁体   English   中英

如何将存储为小端字节数组的 uint16 转换为 int?

[英]How to convert a uint16 stored as a little endian byte array to an int?

我正在接收一些数据,它是代表 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?
    }

谢谢你的帮助 :)

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

在我看来,主要的复杂性在于如何在 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 ,还收到一些其他类型(如字符),那么您可以从 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
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM