如何将存储为小端字节数组的 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
class,偏移量为0,长度等于被包裹的数组长度。您可以使用方法 bb.getShort(i)
访问两个字节,但这将 return 您想要无符号数的负数。
请注意,缓冲区的 "endiness" 仅在您调用 getShort()
等方法时才相关。如果您按所需顺序访问字节,则缓冲区设置并不重要。
按照与 getShort()
方法类似的方法获取数据。这是位 class:
中的元素
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,还有其他一些类型比如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
}
}
我正在接收一些数据,这些数据是代表 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
class,偏移量为0,长度等于被包裹的数组长度。您可以使用方法 bb.getShort(i)
访问两个字节,但这将 return 您想要无符号数的负数。
请注意,缓冲区的 "endiness" 仅在您调用 getShort()
等方法时才相关。如果您按所需顺序访问字节,则缓冲区设置并不重要。
按照与 getShort()
方法类似的方法获取数据。这是位 class:
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,还有其他一些类型比如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
}
}