Java Convert 4 bytes to int
Asked Answered
E

5

15

i was wondering if the solution for this documented here is still the solution or is there any other way getting an int from 4 bytes?

thank you.

EDIT: im getting the byte[] from sockets .read

EDIT: int recvMsgSize = in.read(Data, 0, BufferSize); if recvMsgSize is -1 i know the connection has been dropped.

how do i detect this when im using DataInputStream instead of InputStream?

thanks.

EDIT: apologies for being a yoyo regarding accepting the right answer. but after mihi's updated final response, it would appear that the method is solid and cuts down extended coding and in my opinion best practice.

Expulsion answered 15/5, 2010 at 13:3 Comment(2)
when you get them from the socket input stream, I'd wrap that one into a DataInputStream and use it for reading all kinds of data. Especially since InputStream.read(byte[]) will not guarantee to read the whole byte array... DataInputStream.readFully does.Tver
possible duplicate of [Convert 4 bytes to int ](https://mcmap.net/q/265824/-convert-4-bytes-to-int)Private
T
8

Depending on where you get those 4 bytes from:

http://docs.oracle.com/javase/7/docs/api/java/io/DataInput.html#readInt()

http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#getInt(int)

You can of course still do it manually, but in most cases using one of those (if you have to convert a byte array with lots of bytes, you might want to use a DataInputStream around a ByteArrayInputStream for example) is easier.

Edit: If you need to change the endianness, you will have to use a ByteBuffer, or reverse the bytes yourself, or do the conversion yourself, as DataInput does not support changing the endianness.

Edit2: When you get them from the socket input stream, I'd wrap that one into a DataInputStream and use it for reading all kinds of data. Especially since InputStream.read(byte[]) will not guarantee to fill the whole byte array... DataInputStream.readFully does.

DataInputStream in = new DataInputStream(socket.getInputStream());
byte aByte = in.readByte();
int anInt = in.readInt();
int anotherInt = in.readInt();
short andAShort = in.readShort(); // 11 bytes read :-)
byte[] lotOfBytes = new byte[anInt];
in.readFully(lotOfBytes);

Edit3: When reading multiple times from a stream, they will continue reading where you stopped, i. e. aByte will be byte 0, anInt will be bytes 1 to 4, anotherInt will be bytes 5 to 8, etc. readFully will read on after all that and will block until it has read lotOfbytes.

When the stream stops (the connection drops) you will get EOFException instead of -1, so if you get -1, the int really was -1.

If you do not want to parse any bytes at all, you can skip() them. Parsing one byte in 2 different ways is not possible with DataInputStream (i. e. read first an int from byte 0 to 3, then one from byte 2 to 5), but usually not needed either.

Example:

// read messages (length + data) until the stream ends:
while (true) {
int messageLength;
try {
    messageLength = in.readInt(); // bytes 0 to 3
} catch (EOFException ex) {
    // connection dropped, so handle it, for example
    return;
}
byte[] message = new byte[messageLength];
in.readFully(message);
// do something with the message.
}
// all messages handled.

Hope this answers your additional questions.

Tver answered 15/5, 2010 at 13:9 Comment(7)
@mihi: in.readFully(lotOfBytes); would this read completely after the int message length header? would it read from the beginning or start after the 4 byte int data holder?Expulsion
java.sun.com/j2se/1.4.2/docs/api/java/io/DataInputStream.html ok im studying now :)Expulsion
@mihi: how do i handle a closed/hungup connection using DataInputStream? i.e. -1? do i do a readInt and that would give -1? please advise.Expulsion
int recvMsgSize = in.readInt(); (using DataInputStream is not working in terms or detecting connection drop. please advise.Expulsion
int recvMsgSize = in.read(); solved it. thanks, you posting is the most informative. thanks to everyone else also.Expulsion
no, i get what you are saying but having implementation issues. how do i test for -1 (connection dropped) and then read int from position 0 to position 3?Expulsion
@mihi: Super. thank you for taking the time to update your answer. very helpful.Expulsion
R
22

You have to be very careful with any widening conversion and numeric promotion, but the code below converts 4 byte into int:

    byte b1 = -1;
    byte b2 = -2;
    byte b3 = -3;
    byte b4 = -4;
    int i = ((0xFF & b1) << 24) | ((0xFF & b2) << 16) |
            ((0xFF & b3) << 8) | (0xFF & b4);
    System.out.println(Integer.toHexString(i)); // prints "fffefdfc"

See also

  • Java code To convert byte to Hexadecimal
    • Pay attention to the need to mask with & 0xFF -- you'll probably end up doing a lot of this if you're working with byte since all arithmetic operations promote to int (or long)
Remsen answered 15/5, 2010 at 13:16 Comment(7)
while it looks like it should work, are we sure it doesn't screw up when there's a signed bit around?Lowland
i think you misunderstood. i would like 4 bytes to int. not int to 4 bytes.Expulsion
@ikurtz: fixed. Sorry for misunderstanding.Remsen
@Lo'oris: feel free to check the latest revision.Remsen
And exactly that discussion is the reason you should better use the pre-existing methods in ByteBuffer or DataInput :-) They do work.Tver
I think b1 doesnt need to be & 0xFF for this to workEngender
this works, you may notice: big endian vs little endianWina
A
22

If you have them already in a byte[] array, you can use:

int result = ByteBuffer.wrap(bytes).getInt();

or, if you have Google's guava-libraries on your classpath, you have the shortcut:

int result = Ints.fromByteArray(array);

which has the advantage that you have similarly nice APIs for other types (Longs.fromByteArray, Shorts.fromByteArray, etc).

Annunciate answered 15/5, 2010 at 13:51 Comment(0)
T
8

Depending on where you get those 4 bytes from:

http://docs.oracle.com/javase/7/docs/api/java/io/DataInput.html#readInt()

http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#getInt(int)

You can of course still do it manually, but in most cases using one of those (if you have to convert a byte array with lots of bytes, you might want to use a DataInputStream around a ByteArrayInputStream for example) is easier.

Edit: If you need to change the endianness, you will have to use a ByteBuffer, or reverse the bytes yourself, or do the conversion yourself, as DataInput does not support changing the endianness.

Edit2: When you get them from the socket input stream, I'd wrap that one into a DataInputStream and use it for reading all kinds of data. Especially since InputStream.read(byte[]) will not guarantee to fill the whole byte array... DataInputStream.readFully does.

DataInputStream in = new DataInputStream(socket.getInputStream());
byte aByte = in.readByte();
int anInt = in.readInt();
int anotherInt = in.readInt();
short andAShort = in.readShort(); // 11 bytes read :-)
byte[] lotOfBytes = new byte[anInt];
in.readFully(lotOfBytes);

Edit3: When reading multiple times from a stream, they will continue reading where you stopped, i. e. aByte will be byte 0, anInt will be bytes 1 to 4, anotherInt will be bytes 5 to 8, etc. readFully will read on after all that and will block until it has read lotOfbytes.

When the stream stops (the connection drops) you will get EOFException instead of -1, so if you get -1, the int really was -1.

If you do not want to parse any bytes at all, you can skip() them. Parsing one byte in 2 different ways is not possible with DataInputStream (i. e. read first an int from byte 0 to 3, then one from byte 2 to 5), but usually not needed either.

Example:

// read messages (length + data) until the stream ends:
while (true) {
int messageLength;
try {
    messageLength = in.readInt(); // bytes 0 to 3
} catch (EOFException ex) {
    // connection dropped, so handle it, for example
    return;
}
byte[] message = new byte[messageLength];
in.readFully(message);
// do something with the message.
}
// all messages handled.

Hope this answers your additional questions.

Tver answered 15/5, 2010 at 13:9 Comment(7)
@mihi: in.readFully(lotOfBytes); would this read completely after the int message length header? would it read from the beginning or start after the 4 byte int data holder?Expulsion
java.sun.com/j2se/1.4.2/docs/api/java/io/DataInputStream.html ok im studying now :)Expulsion
@mihi: how do i handle a closed/hungup connection using DataInputStream? i.e. -1? do i do a readInt and that would give -1? please advise.Expulsion
int recvMsgSize = in.readInt(); (using DataInputStream is not working in terms or detecting connection drop. please advise.Expulsion
int recvMsgSize = in.read(); solved it. thanks, you posting is the most informative. thanks to everyone else also.Expulsion
no, i get what you are saying but having implementation issues. how do i test for -1 (connection dropped) and then read int from position 0 to position 3?Expulsion
@mihi: Super. thank you for taking the time to update your answer. very helpful.Expulsion
J
-1

A solution in functional style (just for variety, imho not very convinient in use):

private int addByte (int base, byte appendix) {
    return (base << 4) + appendix;
}

public void test() {
    byte b1 = 5, b2 = 5, byte b3 = 0, b4 = 1;
    int result = addByte (addByte (addByte (addByte (0, b1), b2), b3), b4);
}
Jordon answered 15/5, 2010 at 13:34 Comment(1)
Shouldn't the bit shift be 8, not 4?Polished
C
-4

As mihi said, it depends on where you are getting those bytes from, but this code might be of use:

int myNumber = (((int)byteOne) << 0) |
    (((int)byteTwo) << 8) |
    (((int)byteThree) << 16) |
    (((int)byteFour) << 24);
Cummerbund answered 15/5, 2010 at 13:20 Comment(2)
(int) is superfluous and wrong, you need to undo sign extension with & 0xFF mask.Remsen
This one messes up on signed bits. Polygenelubricants wins.Cummerbund

© 2022 - 2024 — McMap. All rights reserved.