我的数据以字节数组(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。
答案 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);
}