HOWTO · Java

How to Convert Byte Array to Integer in Java

This tutorial demonstrates how to convert a byte array to int in Java.

On this page

Converting a byte array to an integer in Java is a common task when dealing with network protocols, file I/O, or binary data formats. The right approach depends on what the bytes represent: sometimes several bytes encode one int, and sometimes each byte is an independent value. This article covers the core Java methods — ByteBuffer, DataInputStream, manual bit shifting, and BigInteger — plus the byte-order and signedness rules that decide whether the result is correct.

Convert Four Bytes to an int with ByteBuffer

ByteBuffer (in java.nio) is the most direct core-Java tool for this conversion. The wrap method creates a buffer that shares the array’s storage, and getInt() reads four bytes starting at the buffer’s current position and interprets them as one int. Run this example:

import java.nio.ByteBuffer;

public class ByteArrayToInt {
  public static void main(String[] args) {
    byte[] byteArray = {0x00, 0x01, 0x03, 0x10};

    int intValue = ByteBuffer.wrap(byteArray).getInt();

    System.out.println("Converted Integer Value: " + intValue);
  }
}

Output:

Converted Integer Value: 66320

A ByteBuffer is big-endian by default on every platform: the first byte in the array is treated as the most significant byte. If the data was written in little-endian order, select that order explicitly with ByteOrder before reading:

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

public class ByteArrayToIntOrder {
  public static void main(String[] args) {
    byte[] byteArray = {0x00, 0x01, 0x03, 0x10};

    int bigEndianValue = ByteBuffer.wrap(byteArray).getInt();
    int littleEndianValue =
        ByteBuffer.wrap(byteArray).order(ByteOrder.LITTLE_ENDIAN).getInt();

    System.out.println("big-endian: " + bigEndianValue);
    System.out.println("little-endian: " + littleEndianValue);
  }
}

Output:

big-endian: 66320
little-endian: 268632320

Two details matter here. First, getInt() reads at the buffer’s current position and advances it by four, so calling it twice on the same buffer reads the next four bytes; a fresh wrap always starts at position 0. Second, when fewer than four bytes remain, getInt() throws a BufferUnderflowException, so check the input length before reading.

Read Four Bytes with DataInputStream

When the bytes arrive through a stream — or when you want to read several primitive values in sequence — DataInputStream is a good fit. Wrap the array in a ByteArrayInputStream, wrap that in a DataInputStream, and call readInt():

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;

public class ByteArrayToIntWithDataInputStream {
  public static void main(String[] args) throws IOException {
    byte[] byteArray = {0x00, 0x01, 0x03, 0x10};

    try (DataInputStream input =
        new DataInputStream(new ByteArrayInputStream(byteArray))) {
      int intValue = input.readInt();
      System.out.println("Converted Integer Value: " + intValue);
    }
  }
}

Output:

Converted Integer Value: 66320

readInt() always interprets the next four bytes in big-endian order, regardless of the platform. When fewer than four bytes remain in the stream, it throws an EOFException, which you can catch to report a short input instead of crashing:

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;

public class ByteArrayToIntShortInput {
  public static void main(String[] args) throws IOException {
    byte[] byteArray = {0x03, 0x10};

    try (DataInputStream input =
        new DataInputStream(new ByteArrayInputStream(byteArray))) {
      int intValue = input.readInt();
      System.out.println("Converted Integer Value: " + intValue);
    } catch (EOFException e) {
      System.out.println("readInt() needs four bytes, but only " + byteArray.length + " remain");
    }
  }
}

Output:

readInt() needs four bytes, but only 2 remain

Build an int by Shifting Bytes

Shifting the bytes yourself shows exactly how the conversion works and gives full control over order and length. For each byte, shift the accumulated value left by 8 bits and OR in the next byte:

public class ByteArrayToIntManually {
  public static void main(String[] args) {
    byte[] byteArray = {0x00, 0x01, 0x03, 0x10};

    int intValue = 0;

    for (byte b : byteArray) {
      intValue = (intValue << 8) | (b & 0xFF);
    }

    System.out.println("Converted Integer Value: " + intValue);
  }
}

Output:

Converted Integer Value: 66320

The mask b & 0xFF is required because the Java byte type is signed: 0x80 is stored as -128. Without the mask, | would combine 0xFFFFFF80 instead of 0x00000080, corrupting every higher byte. This loop assembles the bytes in big-endian order — the first array element is the most significant byte — and assumes the array holds exactly four bytes. For a different order, iterate the array in the opposite direction; for more bytes, accumulate into a long instead of an int.

Interpret a Byte Array with BigInteger

BigInteger accepts a byte array directly in its constructor and interprets it as a signed, big-endian, two’s-complement number of arbitrary length. intValue() then narrows the result to an int:

import java.math.BigInteger;

public class ByteArrayToIntWithBigInteger {
  public static void main(String[] args) {
    byte[] byteArray = {0x00, 0x01, 0x03, 0x10};

    int intValue = new BigInteger(byteArray).intValue();

    System.out.println("Converted Integer Value: " + intValue);
  }
}

Output:

Converted Integer Value: 66320

Because the interpretation is signed, a leading 1 bit produces a value below 0; pass a signum of 1 as the first constructor argument for the unsigned interpretation. Keep in mind that intValue() keeps only the low 32 bits — it silently truncates values that do not fit in an int:

import java.math.BigInteger;

public class BigIntegerSignAndRange {
  public static void main(String[] args) {
    byte[] allOnes = {(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF};

    System.out.println("signed: " + new BigInteger(allOnes));
    System.out.println("unsigned: " + new BigInteger(1, allOnes));
    System.out.println("narrowed to int: " + new BigInteger(1, allOnes).intValue());
  }
}

Output:

signed: -1
unsigned: 4294967295
narrowed to int: -1

BigInteger is the natural choice when the array is longer than four bytes or when you need the unsigned magnitude before narrowing.

Convert Each Byte Separately

All methods above combine several bytes into one number. If each byte is an independent value — sensor readings, color channels, protocol fields — convert the elements individually instead. Note the distinction: getShort() or readShort() on two bytes produces one combined short, it does not convert each byte separately.

Also remember that the Java byte type is signed, ranging from -128 to 127. When the intent is an unsigned value from 0 to 255, use Byte.toUnsignedInt (available since Java 8) or the equivalent b & 0xFF mask:

public class PrintEachByte {
  public static void main(String[] args) {
    byte[] byteArray = {0x03, 0x04, (byte) 0x80, (byte) 0xFF};

    for (byte b : byteArray) {
      System.out.println("signed: " + b + " unsigned: " + Byte.toUnsignedInt(b));
    }
  }
}

Output:

signed: 3 unsigned: 3
signed: 4 unsigned: 4
signed: -128 unsigned: 128
signed: -1 unsigned: 255

Choose a Method and Handle Edge Cases

Each approach fits a different situation:

  • ByteBuffer is the first choice for reading a four-byte int from an array: it is compact, supports both byte orders through ByteOrder, and provides getLong(), getShort(), and friends for other widths.
  • DataInputStream suits code that already works with streams and needs to read several typed values in sequence; its reads are always big-endian.
  • Manual shifting costs a few more lines but controls order, offset, and width precisely and needs no buffer or stream object.
  • BigInteger handles arrays longer than four bytes and explicit signed or unsigned interpretation before narrowing.
  • Per-byte conversion with Byte.toUnsignedInt applies when every element is its own value rather than part of one number.

Whichever method you choose, check these points before converting:

  • Input length: a four-byte read on a shorter array fails — BufferUnderflowException for ByteBuffer, EOFException for DataInputStream, and an ArrayIndexOutOfBoundsException or silently wrong result for manual code.
  • Byte order: the reader’s order must match the order the bytes were written in; ByteBuffer defaults to big-endian and can be switched with ByteOrder, while DataInputStream reads are always big-endian with no order option.
  • Signedness and range: getInt() and readInt() return a signed int, so an unsigned 32-bit value above Integer.MAX_VALUE appears below 0. Use Integer.toUnsignedLong(intValue) or accumulate into a long when the source data is unsigned.
  • Buffer position: reusing a ByteBuffer continues from its current position, not from the start; call rewind() or wrap again to reread the array.