简体   繁体   English

如何改进此Java代码-将字节数组转换为int

[英]how to improve this java code - converting byte array to int

I have data come back from a BLE device in a byte array (little-endian) and was able to get it working us this code below. 我有一个数据以字节数组(little-endian)的形式从BLE设备返回,并且能够通过下面的代码使它工作。 However Im curious is there a way to write this code in a cleaner way: 但是我很好奇,有没有一种方法可以以更简洁的方式编写此代码:

int val = (Integer.parseInt(String.format("%02x", data[3]), 16) << 24) |    
          (Integer.parseInt(String.format("%02x", data[2]), 16) << 16 ) |
          (Integer.parseInt(String.format("%02x", data[1]), 16) << 8) | 
          (Integer.parseInt(String.format("%02x", data[0]), 16)) << 0;

Here the data coming back printed out as hex: 这里返回的数据以十六进制形式打印出来:

data[0] = 0
data[1] = 0
data[2] = 8
data[3] = 9f

The final int value should be 2207. 最终的int值应为2207。

assuming that your byte array contains more than just 4 bytes and consists of packed binary data it makes sense to use a ByteBuffer, which is designed for these kinds of things. 假设您的字节数组包含的字节数不止4个,并且由打包的二进制数据组成,那么使用ByteBuffer是有意义的,该字节缓冲区是为此类事情而设计的。

ByteBuffer buf = ByteBuffer.wrap(data)
buf.order(ByteOrder.LITTLE_ENDIAN);
int val = buf.getInt(); // read 4 bytes
int val2 = but.getShort(); // read 2
// ... more reads

If the wrapping buffer does not leave the the local scope then escape analysis can kick in and essentially make it a cost-free abstraction. 如果包装缓冲区没有离开本地作用域,则可以进行转义分析,从而使它成为无成本的抽象。

It's unnecessary and inefficient to format as a hexadecimal string and then parse that as an integer. 格式化为十六进制字符串然后将其解析为整数是不必要且效率低下的。 This is equivalent to your code: 这等效于您的代码:

int val = Byte.toUnsignedInt(data[3]) << 24 |
        Byte.toUnsignedInt(data[2]) << 16 |
        Byte.toUnsignedInt(data[1]) << 8 |
        Byte.toUnsignedInt(data[0]);

To conversion to integer is necessary because bytes in Java are signed, for example 0x9f is -97, which if simply converted to int , as it automatically happens when using the << operator, would become 11111111111111111111111110011111 instead of 10011111 what you actually need. 转换为整数是必要的,因为Java中的字节是带符号的,例如0x9f是-97,如果将其简单地转换为int (使用<<运算符时会自动发生),它将变为11111111111111111111111110011111而不是您实际需要的10011111

To avoid the repetition, you can use a loop, for example: 为了避免重复,可以使用循环,例如:

int val = 0;
for (int i = data.length - 1; i >= 0; i--) {
    val <<= 8;
    val |= Byte.toUnsignedInt(data[i]);
}

Note this and your original code gives 2207 if the values of data are reversed, not as you wrote in your question: 请注意,如果data值反转,则原始代码会给出2207,而不是您在问题中所写的:

byte[] data = new byte[]{(byte) 0x9f, 8, 0, 0};
int val = 0;
for (int i=0; i<4; i++)
{
  val |= Integer.parseInt(String.format("%02x", data[i]), 16) << (i*8);
}

or just 要不就

int val = 0;
for (int i=0; i<4; i++)
{
  val |= data[i] << (i*8);
}

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

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