HOWTO · Java

Konvertieren Sie Byte-Array in Integer in Java

Dieses Tutorial zeigt, wie man in Java ein Byte-Array in int umwandelt

Auf dieser Seite

Ein Byte-Array in Java in einen int-Wert umzuwandeln, ist eine häufige Aufgabe bei der Arbeit mit Netzwerkprotokollen, Datei-I/O oder binären Datenformaten. Der passende Ansatz hängt davon ab, was die Bytes darstellen: Manchmal codieren mehrere Bytes gemeinsam einen int, manchmal ist jedes Byte ein eigenständiger Wert. Dieser Artikel behandelt die zentralen Java-Methoden — ByteBuffer, DataInputStream, manuelle Bitverschiebung und BigInteger — sowie die Regeln zu Byte-Reihenfolge und Vorzeichen, die darüber entscheiden, ob das Ergebnis korrekt ist.

Vier Bytes mit ByteBuffer in einen int umwandeln

ByteBuffer (in java.nio) ist das direkteste Standard-Java-Werkzeug für diese Umwandlung. Die Methode wrap erzeugt einen Puffer, der sich den Speicher des Arrays teilt, und getInt() liest vier Bytes ab der aktuellen Position des Puffers und interpretiert sie als einen int-Wert. Führen Sie dieses Beispiel aus:

Der Code und die angezeigte Bezeichnung in der Ausgabe bleiben unverändert auf Englisch.

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

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);
  }
}

Ausgabe:

Converted Integer Value: 66320

Ein ByteBuffer verwendet auf jeder Plattform standardmäßig Big-Endian: Das erste Byte im Array gilt als höchstwertiges Byte. Wenn die Daten in Little-Endian-Reihenfolge geschrieben wurden, wählen Sie diese Reihenfolge vor dem Lesen explizit mit ByteOrder:

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);
  }
}

Ausgabe:

big-endian: 66320
little-endian: 268632320

Zwei Details sind hier wichtig. Erstens liest getInt() ab der aktuellen Position des Puffers und setzt sie um vier Bytes weiter; ein zweiter Aufruf auf demselben Puffer liest daher die nächsten vier Bytes, und ein neues wrap beginnt immer bei Position 0. Zweitens löst getInt() eine BufferUnderflowException aus, wenn weniger als vier Bytes übrig sind. Prüfen Sie deshalb vor dem Lesen die Länge der Eingabe.

Vier Bytes mit DataInputStream lesen

Wenn die Bytes über einen Stream eintreffen — oder wenn Sie mehrere primitive Werte nacheinander lesen möchten — ist DataInputStream gut geeignet. Verpacken Sie das Array in einen ByteArrayInputStream, diesen wiederum in einen DataInputStream, und rufen Sie readInt() auf:

Der Code und die angezeigte Bezeichnung in der Ausgabe bleiben unverändert auf Englisch.

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

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);
    }
  }
}

Ausgabe:

Converted Integer Value: 66320

readInt() interpretiert die nächsten vier Bytes unabhängig von der Plattform immer in Big-Endian-Reihenfolge. Wenn im Stream weniger als vier Bytes übrig sind, löst die Methode eine EOFException aus. Sie können diese Ausnahme abfangen, um eine zu kurze Eingabe zu melden, statt das Programm abstürzen zu lassen; die Meldung im Beispiel bleibt unverändert auf Englisch:

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");
    }
  }
}

Ausgabe:

readInt() needs four bytes, but only 2 remain

Ein int durch Verschieben von Bytes zusammensetzen

Wenn Sie die Bytes selbst verschieben, wird genau sichtbar, wie die Umwandlung funktioniert, und Sie erhalten die volle Kontrolle über Reihenfolge und Länge. Verschieben Sie für jedes Byte den bisher akkumulierten Wert um 8 Bits nach links und verknüpfen Sie das nächste Byte bitweise mit ODER:

Der Code und die angezeigte Bezeichnung in der Ausgabe bleiben unverändert auf Englisch.

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

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);
  }
}

Ausgabe:

Converted Integer Value: 66320

Die Maske b & 0xFF ist erforderlich, weil der Java-Typ byte vorzeichenbehaftet ist: 0x80 wird als -128 gespeichert. Ohne die Maske würde | den Wert 0xFFFFFF80 statt 0x00000080 einbeziehen und jedes höherwertige Byte verfälschen. Diese Schleife setzt die Bytes in Big-Endian-Reihenfolge zusammen — das erste Array-Element ist das höchstwertige Byte — und setzt voraus, dass das Array genau vier Bytes enthält. Für eine andere Reihenfolge durchlaufen Sie das Array in umgekehrter Richtung; für mehr Bytes akkumulieren Sie den Wert in einem long statt in einem int.

Ein Byte-Array mit BigInteger interpretieren

BigInteger nimmt im Konstruktor direkt ein Byte-Array entgegen und interpretiert es als vorzeichenbehaftete Big-Endian-Zahl beliebiger Länge im Zweierkomplement. intValue() verengt das Ergebnis anschließend auf einen int:

Der Code und die angezeigte Bezeichnung in der Ausgabe bleiben unverändert auf Englisch.

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

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);
  }
}

Ausgabe:

Converted Integer Value: 66320

Da die Interpretation vorzeichenbehaftet ist, erzeugt ein führendes 1-Bit einen Wert kleiner als 0. Übergeben Sie für die vorzeichenlose Interpretation den Signum-Wert 1 als erstes Konstruktorargument. Beachten Sie, dass intValue() nur die unteren 32 Bits behält — Werte, die nicht in einen int passen, werden ohne Hinweis abgeschnitten. Die Bezeichnungen in der folgenden Ausgabe bleiben unverändert auf Englisch:

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());
  }
}

Ausgabe:

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

BigInteger ist die naheliegende Wahl, wenn das Array länger als vier Bytes ist oder wenn Sie den vorzeichenlosen Betrag vor der Verengung benötigen.

Jedes Byte separat umwandeln

Alle bisherigen Methoden fassen mehrere Bytes zu einer Zahl zusammen. Wenn jedes Byte ein eigenständiger Wert ist — etwa ein Sensormesswert, ein Farbkanal oder ein Protokollfeld — wandeln Sie die Elemente stattdessen einzeln um. Beachten Sie den Unterschied: getShort() oder readShort() erzeugt aus zwei Bytes einen gemeinsamen short-Wert und wandelt nicht jedes Byte separat um.

Denken Sie außerdem daran, dass der Java-Typ byte vorzeichenbehaftet ist und den Bereich von -128 bis 127 abdeckt. Wenn ein vorzeichenloser Wert von 0 bis 255 gemeint ist, verwenden Sie Byte.toUnsignedInt (seit Java 8 verfügbar) oder die gleichwertige Maske b & 0xFF:

Der Code sowie die englischen Bezeichnungen für beide Interpretationen bleiben in der Ausgabe unverändert.

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

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));
    }
  }
}

Ausgabe:

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

Eine Methode auswählen und Grenzfälle behandeln

Jeder Ansatz eignet sich für eine andere Situation:

  • ByteBuffer ist die erste Wahl, um einen Vier-Byte-int aus einem Array zu lesen: Die Methode ist kompakt, unterstützt über ByteOrder beide Byte-Reihenfolgen und bietet mit getLong(), getShort() und verwandten Methoden auch andere Breiten an.
  • DataInputStream eignet sich für Code, der bereits mit Streams arbeitet und mehrere typisierte Werte nacheinander lesen muss; seine Lesevorgänge sind immer Big-Endian.
  • Das manuelle Verschieben kostet ein paar Zeilen mehr, steuert aber Reihenfolge, Offset und Breite präzise und benötigt weder ein Puffer- noch ein Stream-Objekt.
  • BigInteger verarbeitet Arrays mit mehr als vier Bytes sowie eine explizit vorzeichenbehaftete oder vorzeichenlose Interpretation vor der Verengung.
  • Die Umwandlung pro Byte mit Byte.toUnsignedInt ist sinnvoll, wenn jedes Element einen eigenen Wert darstellt und nicht Teil einer gemeinsamen Zahl ist.

Unabhängig davon, für welche Methode Sie sich entscheiden, prüfen Sie vor dem Umwandeln diese Punkte:

  • Eingabelänge: Ein Vier-Byte-Lesevorgang auf einem kürzeren Array schlägt fehl — mit BufferUnderflowException bei ByteBuffer, EOFException bei DataInputStream und mit einer ArrayIndexOutOfBoundsException oder einem stillschweigend falschen Ergebnis bei manuellem Code.
  • Byte-Reihenfolge: Die Reihenfolge beim Lesen muss zu der Reihenfolge passen, in der die Bytes geschrieben wurden. ByteBuffer verwendet standardmäßig Big-Endian und kann mit ByteOrder umgestellt werden, während DataInputStream ohne Reihenfolgenoption immer Big-Endian liest.
  • Vorzeichen und Wertebereich: getInt() und readInt() geben einen vorzeichenbehafteten int zurück, sodass ein vorzeichenloser 32-Bit-Wert oberhalb von Integer.MAX_VALUE kleiner als 0 erscheint. Verwenden Sie Integer.toUnsignedLong(intValue) oder akkumulieren Sie den Wert in einem long, wenn die Quelldaten vorzeichenlos sind.
  • Pufferposition: Ein wiederverwendeter ByteBuffer liest ab seiner aktuellen Position weiter, nicht ab dem Anfang. Rufen Sie rewind() auf oder verwenden Sie wrap erneut, um das Array erneut zu lesen.