简体   繁体   中英

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. 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.

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.

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.

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:

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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