29

I have a byte[] that I've read from a file, and I want to get an int from two bytes in it. Here's an example:

byte[] bytes = new byte[] {(byte)0x00, (byte)0x2F, (byte)0x01, (byte)0x10, (byte)0x6F};
int value = bytes.getInt(2,4); //This method doesn't exist

This should make value equal to 0x0110, or 272 in decimal. But obviously, byte[].getInt() doesn't exist. How can I accomplish this task?

The above array is just an example. Actual values are unknown to me.

Alexis King
  • 43,109
  • 15
  • 131
  • 205
  • the reason the answers work is that the bytes are promoted to integers in case that's what was causing you trouble understanding. "bytes[2] * 256" doesn't fit in a byte, but it's not an issue because "256" is an integer, etc. – SyntaxT3rr0r Jan 22 '11 at 16:26
  • 1
    possible duplicate of [Convert 4 bytes to int ](http://stackoverflow.com/questions/2383265/convert-4-bytes-to-int) – finnw Jan 22 '11 at 16:32

6 Answers6

51

You should just opt for the simple:

int val = ((bytes[2] & 0xff) << 8) | (bytes[3] & 0xff);

You could even write your own helper function getBytesAsWord (byte[] bytes, int start) to give you the functionality if you didn't want the calculations peppering your code but I think that would probably be overkill.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 4
    Ideally it should be (b1 << 8) | (b2 & 0x00ff) If second byte value is greater than 128, the above conversion gives incorrect value, as java considers the byte as negative int. – Gopi Aug 14 '14 at 12:09
  • Why the `0xff`? In other words, what's the difference to `bytes[0] << 8 | bytes[1]`? – arve0 Jul 27 '16 at 19:51
6

Here's a nice simple reliable way.

    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4);
    // by choosing big endian, high order bytes must be put
    // to the buffer before low order bytes
    byteBuffer.order(ByteOrder.BIG_ENDIAN);
    // since ints are 4 bytes (32 bit), you need to put all 4, so put 0
    // for the high order bytes
    byteBuffer.put((byte)0x00);
    byteBuffer.put((byte)0x00);
    byteBuffer.put((byte)0x01);
    byteBuffer.put((byte)0x10);
    byteBuffer.flip();
    int result = byteBuffer.getInt();
Matt
  • 11,523
  • 2
  • 23
  • 33
6

Try:

public static int getInt(byte[] arr, int off) {
  return arr[off]<<8 &0xFF00 | arr[off+1]&0xFF;
} // end of getInt

Your question didn't indicate what the two args (2,4) meant. 2 and 4 don't make sense in your example as indices in the array to find ox01 and 0x10, I guessed you wanted to take two consecutive element, a common thing to do, so I used off and off+1 in my method.

You can't extend the byte[] class in java, so you can't have a method bytes.getInt, so I made a static method that uses the byte[] as the first arg.

The 'trick' to the method is that you bytes are 8 bit signed integers and values over 0x80 are negative and would be sign extended (ie 0xFFFFFF80 when used as an int). That is why the '&0xFF' masking is needed. the '<<8' shifts the more significant byte 8 bits left. The '|' combines the two values -- just as '+' would. The order of the operators is important because << has highest precedence, followed by & followed by | -- thus no parentheses are needed.

Ribo
  • 3,363
  • 1
  • 29
  • 35
  • Thx for this nice explanation. For the same thing but signed value, I used: `return arr[off]<<8 | arr[off+1]&0xFF;` – Daniel Alder Feb 05 '16 at 18:30
1

Alternatively, you could use:

int val = (bytes[2] << 8) + bytes[3]
David Weiser
  • 5,190
  • 4
  • 28
  • 35
  • 3
    No: it will return a negative int if bytes[2] is bigger than 0x7f. The "& 0xff" from paxdiablo's answer is required. – Francois Jun 24 '15 at 13:21
0

The Google Base16 class is from Guava-14.0.1.

new BigInteger(com.google.common.io.BaseEncoding.base16().encode(bytesParam),16).longValue();
Koekiebox
  • 5,793
  • 14
  • 53
  • 88
0

You can use ByteBuffer. It has the getInt method you are searching for and many other useful methods

matteo rulli
  • 1,443
  • 2
  • 18
  • 30