Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert 4 bytes to int

I'm reading a binary file like this:

InputStream in = new FileInputStream( file );
byte[] buffer = new byte[1024];
while( ( in.read(buffer ) > -1 ) {

   int a = // ??? 
}

What I want to do it to read up to 4 bytes and create a int value from those but, I don't know how to do it.

I kind of feel like I have to grab 4 bytes at a time, and perform one "byte" operation ( like >> << >> & FF and stuff like that ) to create the new int

What's the idiom for this?

EDIT

Ooops this turn out to be a bit more complex ( to explain )

What I'm trying to do is, read a file ( may be ascii, binary, it doesn't matter ) and extract the integers it may have.

For instance suppose the binary content ( in base 2 ) :

00000000 00000000 00000000 00000001
00000000 00000000 00000000 00000010

The integer representation should be 1 , 2 right? :- / 1 for the first 32 bits, and 2 for the remaining 32 bits.

11111111 11111111 11111111 11111111

Would be -1

and

01111111 11111111 11111111 11111111

Would be Integer.MAX_VALUE ( 2147483647 )

like image 702
OscarRyz Avatar asked Mar 04 '10 22:03

OscarRyz


People also ask

How do you convert bytes to integers?

A byte value can be interchanged to an int value using the int. from_bytes() function. The int. from_bytes() function takes bytes, byteorder, signed, * as parameters and returns the integer represented by the given array of bytes.

What is a 4 byte integer?

The SQL INTEGER data type can hold integer values in the range -2,147,483,647 - 2,147,483,647. The SQL SERIAL data type holds four-byte integer values that the database server automatically assigns when a value is inserted in the column.

How are 4 bytes int stored?

Integers are commonly stored using a word of memory, which is 4 bytes or 32 bits, so integers from 0 up to 4,294,967,295 (232 - 1) can be stored. Below are the integers 1 to 5 stored as four-byte values (each row represents one integer).


10 Answers

ByteBuffer has this capability, and is able to work with both little and big endian integers.

Consider this example:


//  read the file into a byte array
File file = new File("file.bin");
FileInputStream fis = new FileInputStream(file);
byte [] arr = new byte[(int)file.length()];
fis.read(arr);

//  create a byte buffer and wrap the array
ByteBuffer bb = ByteBuffer.wrap(arr);

//  if the file uses little endian as apposed to network
//  (big endian, Java's native) format,
//  then set the byte order of the ByteBuffer
if(use_little_endian)
    bb.order(ByteOrder.LITTLE_ENDIAN);

//  read your integers using ByteBuffer's getInt().
//  four bytes converted into an integer!
System.out.println(bb.getInt());

Hope this helps.

like image 175
Tom Avatar answered Oct 05 '22 14:10

Tom


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

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

source: here

like image 38
iTEgg Avatar answered Oct 05 '22 12:10

iTEgg


You should put it into a function like this:

public static int toInt(byte[] bytes, int offset) {
  int ret = 0;
  for (int i=0; i<4 && i+offset<bytes.length; i++) {
    ret <<= 8;
    ret |= (int)bytes[i] & 0xFF;
  }
  return ret;
}

Example:

byte[] bytes = new byte[]{-2, -4, -8, -16};
System.out.println(Integer.toBinaryString(toInt(bytes, 0)));

Output:

11111110111111001111100011110000

This takes care of running out of bytes and correctly handling negative byte values.

I'm unaware of a standard function for doing this.

Issues to consider:

  1. Endianness: different CPU architectures put the bytes that make up an int in different orders. Depending on how you come up with the byte array to begin with you may have to worry about this; and

  2. Buffering: if you grab 1024 bytes at a time and start a sequence at element 1022 you will hit the end of the buffer before you get 4 bytes. It's probably better to use some form of buffered input stream that does the buffered automatically so you can just use readByte() repeatedly and not worry about it otherwise;

  3. Trailing Buffer: the end of the input may be an uneven number of bytes (not a multiple of 4 specifically) depending on the source. But if you create the input to begin with and being a multiple of 4 is "guaranteed" (or at least a precondition) you may not need to concern yourself with it.

to further elaborate on the point of buffering, consider the BufferedInputStream:

InputStream in = new BufferedInputStream(new FileInputStream(file), 1024);

Now you have an InputStream that automatically buffers 1024 bytes at a time, which is a lot less awkward to deal with. This way you can happily read 4 bytes at a time and not worry about too much I/O.

Secondly you can also use DataInputStream:

InputStream in = new DataInputStream(new BufferedInputStream(
                     new FileInputStream(file), 1024));
byte b = in.readByte();

or even:

int i = in.readInt();

and not worry about constructing ints at all.

like image 35
cletus Avatar answered Oct 05 '22 14:10

cletus


just see how DataInputStream.readInt() is implemented;

    int ch1 = in.read();
    int ch2 = in.read();
    int ch3 = in.read();
    int ch4 = in.read();
    if ((ch1 | ch2 | ch3 | ch4) < 0)
        throw new EOFException();
    return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
like image 20
Santhosh Kumar Tekuri Avatar answered Oct 05 '22 13:10

Santhosh Kumar Tekuri


The easiest way is:

RandomAccessFile in = new RandomAccessFile("filename", "r"); 
int i = in.readInt();

-- or --

DataInputStream in = new DataInputStream(new BufferedInputStream(
    new FileInputStream("filename"))); 
int i = in.readInt();
like image 45
Taylor Leese Avatar answered Oct 05 '22 14:10

Taylor Leese


try something like this:

a = buffer[3];
a = a*256 + buffer[2];
a = a*256 + buffer[1];
a = a*256 + buffer[0];

this is assuming that the lowest byte comes first. if the highest byte comes first you might have to swap the indices (go from 0 to 3).

basically for each byte you want to add, you first multiply a by 256 (which equals a shift to the left by 8 bits) and then add the new byte.

like image 39
stmax Avatar answered Oct 05 '22 13:10

stmax


Here is a simple solution that works for me:

int value = (a&255)+((b&255)<<8)+((c&255)<<16)+((d&255)<<24);

a is the least significant byte

b is the second least significant byte

c is the second most significant byte

and d is the most significant byte

like image 34
Bluesillybeard2 Avatar answered Oct 05 '22 13:10

Bluesillybeard2


for (int i = 0; i < buffer.length; i++)
{
   a = (a << 8) | buffer[i];
   if (i % 3 == 0)
   {
      //a is ready
      a = 0;
   }       
}
like image 44
Andrey Avatar answered Oct 05 '22 12:10

Andrey


You can also use BigInteger for variable length bytes. You can convert it to Long, Integer or Short, whichever suits your needs.

new BigInteger(bytes).intValue();

or to denote polarity:

new BigInteger(1, bytes).intValue();
like image 24
Jamel Toms Avatar answered Oct 05 '22 12:10

Jamel Toms


For reading unsigned 4 bytes as integer we should use a long variable, because the sign bit is considered as part of the unsigned number.

long result = (((bytes[0] << 8 & bytes[1]) << 8 & bytes[2]) << 8) & bytes[3]; 
result = result & 0xFFFFFFFF;

This is tested well worked function

like image 41
Mounir Avatar answered Oct 05 '22 14:10

Mounir