如何改进这个java代码 - 将字节数组转换为int

时间:2016-10-28 18:50:21

标签: java byte endianness

我的数据以字节数组(little-endian)从BLE设备返回,并且能够让我们使用下面的代码。但是我很好奇有没有办法以更清洁的方式编写这段代码:

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;

这里回来的数据打印为十六进制:

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

最终的int值应为2207。

3 个答案:

答案 0 :(得分:1)

假设您的字节数组包含的字节数不仅仅超过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

如果包装缓冲区没有离开本地范围,则转义分析可以启动并基本上使其成为一个免费的抽象。

答案 1 :(得分:0)

格式化为十六进制字符串然后将其解析为整数是不必要且低效的。这相当于您的代码:

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

要转换为整数是必要的,因为Java中的字节是有符号的, 例如0x9f是-97,如果只是转换为int,因为它在使用<<运算符时自动发生,将变为11111111111111111111111110011111而不是10011111你真正需要的是什么。

为避免重复,您可以使用循环,例如:

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

请注意这一点,如果data的值被撤消,原始代码会给出2207,而不是您在问题中写的那样:

byte[] data = new byte[]{(byte) 0x9f, 8, 0, 0};

答案 2 :(得分:-3)

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

或只是

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