29

I want to perform a conversion without resorting to some implementation-dependent trick. Any tips?

1
  • 2
    What do you want to convert? Your question isn't specific. What are the four bytes of your array? Commented Apr 11, 2011 at 1:53

7 Answers 7

84

You need to know the endianness of your bytes.

Assuming (like @WhiteFang34) that bytes is a byte[] of length 4, then...

Big-endian:

int x = java.nio.ByteBuffer.wrap(bytes).getInt();

Little-endian:

int x = java.nio.ByteBuffer.wrap(bytes).order(java.nio.ByteOrder.LITTLE_ENDIAN).getInt();
Sign up to request clarification or add additional context in comments.

1 Comment

+1 this does work and provides a good option for little-endian support. I was wondering if/where Java had support to do this. It does create an object to go this route though. So it's not as efficient, although I doubt it matters for most uses.
29

Assuming bytes is a byte[4] of an integer in big-endian order, typically used in networking:

int value = ((bytes[0] & 0xFF) << 24) | ((bytes[1] & 0xFF) << 16)
        | ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF);

The & 0xFF are necessary because byte is signed in Java and you need to retain the signed bit here. You can reverse the process with this:

bytes[0] = (byte) ((value >> 24) & 0xFF);
bytes[1] = (byte) ((value >> 16) & 0xFF);
bytes[2] = (byte) ((value >> 8) & 0xFF);
bytes[3] = (byte) (value & 0xFF);

3 Comments

I might be misreading but I think that's big-endian the way you wrote it.
@David: it is. Thanks, I did indeed mislabel it the first time.
Why the first & 0xff is needed when converting from byte[] to int? Aren't leading 1s for signed values dropped by << 24? As I understand it ((bytes[0] & 0xFF) << 24) is the same as ((bytes[0] << 24) in this case. If byte[0] is signed it is converted to signed int but << 24 drops everything except the original byte's 8 bits. As well I think & 0xff is used to drop leading bits with value 1 for signed values so that they are not ORed to 0 bits from previous operation. Isn't saying that & 0xff is necessary to retain the signed bit wrong?
6

Not sure if this is correct java syntax, but how about:

int value = 0;
for (i = 0; i <= 3; i++)
    value = (value << 8) + (bytes[i] & 0xFF);

2 Comments

you should 0xff your bytes[i] because a byte (in Java) can be nagative and Java will then convert your byte into a negative integer instead of a value between 0-255
This does not work, it always returns 0. You need parentheses to avoid operator precedence: value = (value << 8) + (bytes[i] & 0xFF);
6

You need to specify the byte order of the array, but assuming that the bytes[0] is the most significant byte then:

int res = ((bytes[0] & 0xff) << 24) | ((bytes[1] & 0xff) << 16) |
          ((bytes[2] & 0xff) << 8)  | (bytes[3] & 0xff);

This code is 100% portable, assuming that you use the reverse algorithm to create the byte array in the first place.


Byte order problems arise in languages where you can cast between a native integer type and byte array type ... and then discover that different architectures store the bytes of an integer in different orders.

You can't do that cast in Java. So for Java to Java communication, this should not be an issue.

However, if you are sending or receiving packets to some remote application that is implemented in (say) C or C++, you need to "know" what byte order is being used in the network packets. Some alternative strategies for knowing / figuring this out are:

  • Everyone uses "network order" (big-endian) for stuff on the wire as per the example code above. Non-java applications on little-endian machines need to flip the bytes.

  • The sender finds out what order the receiver expects and uses that order when assembling the data.

  • The receiver figures out what order the sender used (e.g. via a flag in the packet) and decodes accordingly.

The first approach is simplest and most widely used, though it does result in 2 unnecessary endian-ness conversions if both the sender and receiver are little-endian.

See http://en.wikipedia.org/wiki/Endianness

4 Comments

Is there any way to do this through the standard library? I don't feel too good about assuming things are the byte order of the machines I'm sending packets to...
@Alex: the byte order of the machine doesn't matter in this calculation, it's the byte order of your array that is important. You'll have to specify that even if you do use the standard library (if there is a standard method to do this... I don't remember one).
You need to & 0xFF each of the bytes because byte is signed in Java. The signed bit gets in the way for any number that uses the first bit of any of the bytes. E.g. try going backwards from an integer like 384 to a byte array, when you run your code to get the integer back you'll get -128 instead of 384.
You need parentheses now to keep the & 0xFF applied to the byte. Otherwise the << takes precedence. You'll be getting 128 for 384 in my example without them :)
1

Assuming your byte[] come from somewhere e.g. a stream you can use

DataInputStream dis = ... // can wrap a new ByteArrayInputStream(bytes)
int num = dis.readInt(); // assume big-endian.

or

ByteChannel bc = ... // can be a SocketChannel
ByteBuffer bb = ByteBuffer.allocate(64*1024);

bc.read(bb);
bb.flip();
if (bb.remaining()<4) // not enough data

int num = bb.getInt();

When you send data, you should know if you are sending big-endian or little endian. You have to assume other things such as whether you are sending a 4-byte signed integer. A binary protocol is full of assumptions. (Which makes it more compact and faster, but more brittle than text)

If you don't want to be making as many assumptions, send text.

Comments

1

WE can also use following to make it more dynamic byte array size
BigEndian Format:

public static int pareAsBigEndianByteArray(byte[] bytes) {
    int factor = bytes.length - 1;
    int result = 0;
    for (int i = 0; i < bytes.length; i++) {
        if (i == 0) {
            result |= bytes[i] << (8 * factor--);
        } else {
            result |= bytes[i] << (8 * factor--);
        }
    }
    return result;
}

Little Endian Format :

public static int pareAsLittleEndianByteArray(byte[] bytes) {
    int result = 0;
    for (int i = 0; i < bytes.length; i++) {
        if (i == 0) {
            result |= bytes[i] << (8 * i);
        } else {
            result |= bytes[i] << (8 * i);
        }
    }
    return result;
}

This will helps you lot for converting bytes to int values

Comments

-2
public static int toInt( byte[] bytes ) {
int result = 0;
for (int i=0; i<3; i++) {
  result = ( result << 8 ) - Byte.MIN_VALUE + (int) bytes[i];
}
return result;
}

1 Comment

This does not work. A byte array of all zeros returns 8421504.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.