Die Klasse ByteArrayInputStream im Paket java.io kann zum Lesen eines Eingabearrays (von Bytes) verwendet werden.

Um einen Byte-Array-Eingabestream zu erstellen, müssen wir zunächst das Paket java.io.ByteArrayInputStream importieren. Nachdem wir das Paket importiert haben, stehen uns zwei Konstruktoren zum Erstellen eines Eingabestreams zur Verfügung:


ByteArrayInputStream input = new ByteArrayInputStream(arr);
ByteArrayInputStream input = new ByteArrayInputStream(arr, 2, 2);
    

Es gibt 4 Felder innerhalb der Klasse:


// Byte array provided by the creator of the stream
protected byte buf[];

// Index of the next character to read from the input stream's buffer
protected int pos;

// Current marked position in the stream
protected int mark = 0;

// Index is one greater than the last valid character in the input stream's buffer
protected int count;
    

Und hier sind unsere Konstrukteure:


public ByteArrayInputStream(byte buf[]) {
    this.buf = buf;
    this.pos = 0;
    this.count = buf.length;
}

public ByteArrayInputStream(byte buf[], int offset, int length) {
    this.buf = buf;
    this.pos = offset;
    this.count = Math.min(offset + length, buf.length);
    this.mark = offset;
}
    

Methoden der ByteArrayInputStream-Klasse

Methode Aktion
int read() Liest das nächste Datenbyte aus diesem Eingabestream.
int read(byte b[], int off, int len) Liest mehrere Bytes aus dem Eingabestream und speichert sie im Pufferarray b .
off ist ein Offset in das Zielarray b .
len ist die maximale Anzahl der zu lesenden Bytes.
langer Sprung (langes n) Überspringt n Bytes der Eingabe aus diesem Eingabestream. Gibt die Anzahl der übersprungenen Bytes zurück (sie kann kleiner als n sein, wenn wir das Ende des Eingabestreams erreichen).
int verfügbar() Gibt die Anzahl der verbleibenden Bytes zurück, die aus diesem Eingabestream gelesen (oder übersprungen) werden können.
void reset() Setzt den Puffer auf die markierte Position zurück. Die markierte Position ist 0, es sei denn, es wird eine andere Position markiert oder im Konstruktor ein anderer Offset angegeben.
boolean markSupported() Überprüft, ob dieser InputStream das Markieren/Zurücksetzen unterstützt. Gibt true für ByteArrayInputStream zurück .
void close() Macht nichts.
void mark(int readAheadLimit) Legt die festmarkierenFeld gleich der aktuellen Position. Wenn die Reset- Methode aufgerufen wird, beginnt das nachfolgende Lesen an dieser Position. Der Parameter readAheadLimit wird nicht verwendet und hat keinen Einfluss auf das Verhalten der Methode.

Schauen wir uns diese Methoden genauer an und sehen, wie sie in der Praxis funktionieren.

lesen()

Wenn Sie Bytes aus einem ByteArrayInputStream wie aus einem gewöhnlichen InputStream lesen möchten , können Sie die Methode read() verwenden.


public static void main(String[] args) {
   byte[] array = {1, 2, 3, 4};

   try (ByteArrayInputStream input = new ByteArrayInputStream(array)) {
       for (int i = 0; i < array.length; i++) {
           int data = input.read();
           System.out.print(data + ", ");
       }
   } catch (IOException e) {
       e.printStackTrace();
   }
}
    

verfügbar()

Wenn Sie überprüfen möchten, ob sich etwas in Ihrem Puffer befindet, können Sie die Methode available() aufrufen .


public static void main(String[] args) {
   byte[] array = {1, 2, 3, 4};

   try (ByteArrayInputStream input = new ByteArrayInputStream(array)) {
       System.out.println("Bytes available for reading: " + input.available());

       input.read();
       System.out.println("Bytes available for reading " + input.available());

       input.read();
       System.out.println("Bytes available for reading " + input.available());
   } catch (IOException e) {
       e.printStackTrace();
   }
}
    

Wir werden sehen, dass sich die Anzahl der zum Lesen verfügbaren Bytes nach jedem Lesevorgang aus dem Puffer ändert.

Ausgang:

Zum Lesen verfügbare Bytes: 4
Zum Lesen verfügbare Bytes: 3
Zum Lesen verfügbare Bytes: 2

überspringen(langes n)

Mit der Methode „skip()“ können Sie eine bestimmte Anzahl von Bytes überspringen und nicht lesen.


public static void main(String[] args) {
   byte[] array = {1, 2, 3, 4};

   try (ByteArrayInputStream input = new ByteArrayInputStream(array)) {
       input.skip(2);

       while (input.available() != 0) {
           int data = input.read();
           System.out.print(data + ", ");
       }
   } catch (IOException e) {
       e.printStackTrace();
   }
}
    

Ausgang:

3, 4,

zurücksetzen()

Diese Methode setzt die Position des gepufferten Streams auf die zuletzt markierte Position zurück. Es ist Position 0, sofern keine andere Markierung gesetzt ist.


public static void main(String[] args) {
   byte[] buf = {65, 66, 67, 68, 69};
   try (ByteArrayInputStream input = new ByteArrayInputStream(buf)) {
       System.out.println("Read: " + input.read());
       System.out.println("Read: " + input.read());
       System.out.println("Read: " + input.read());
       System.out.println("Read: " + input.read());

       System.out.println("Calling reset() method");
       input.reset();
       System.out.println("Read: " + input.read());
       System.out.println("Read: " + input.read());
   } catch (IOException e) {
       e.printStackTrace();
   }
}
    

Wir werden sehen, dass der Aufruf der Methode „reset()“ uns zum Startpunkt unseres Streams führt.

Ausgang:

Gelesen: 65
Gelesen: 66
Gelesen: 67
Gelesen: 68
Aufruf der Methode „reset()“
Gelesen: 65
Gelesen: 66

mark(int readAheadLimit)

Die Methode mark() der Klasse ByteArrayInputStream setzt die interne Markierung an der aktuellen Byte-Position, also unmittelbar nach dem zuvor gelesenen Byte. Diese Methode benötigt einen Parameter, der angibt, wie viele Bytes nach der Markierung gelesen werden können, bevor der Stream ungültig wird. Wenn die Markierung nicht explizit festgelegt ist, markiert ein ByteArrayInputStream standardmäßig die Position 0 oder die Position des an seinen Konstruktor übergebenen Offsets. Es ist wichtig zu beachten, dass die Markierung readAheadLimit für diese Klasse irrelevant ist.


/* Note: For this class, {@code readAheadLimit}
*  has no meaning.
*
* @since   1.1
*/
public void mark(int readAheadLimit) {
   mark = pos;
}
    

Hier ist ein Beispiel für das Setzen einer Markierung in einem ByteArrayInputStream mithilfe seiner Methoden mark() und reset() . Wir werden dem vorherigen Beispiel einen Aufruf der Methode mark() hinzufügen:


public static void main(String[] args) {
   byte[] buf = {65, 66, 67, 68, 69};
   try (ByteArrayInputStream input = new ByteArrayInputStream(buf)) {
       System.out.println("Read: " + input.read());
       System.out.println("Read: " + input.read());
       System.out.println("Read: " + input.read());
       input.mark(5);

       System.out.println("Read: " + input.read());
       System.out.println("Read: " + input.read());

       System.out.println("Calling reset() method");
       input.reset();

       System.out.println("Read: " + input.read());
       System.out.println("Read: " + input.read());

   } catch (IOException e) {
       e.printStackTrace();
   }
}
    

Wir können sehen, dass sich die Position des aktuellen Streams geändert hat.

Ausgang:

Gelesen: 65
Gelesen: 66
Gelesen: 67
Gelesen: 68
Gelesen: 69
Aufruf der Methode „reset()“
Gelesen: 68
Gelesen: 69

markSupported()

Mit der Methode markSupported() können Sie prüfen, ob eine Markierung gesetzt werden kann. Um zu verstehen, woher der Rückgabewert kommt, gehen wir zum Code der Methode:


/**
* Tests if this {@code InputStream} supports mark/reset. The
* {@code markSupported} method of {@code ByteArrayInputStream}
* always returns {@code true}.
*
* @since   1.1
*/
public boolean markSupported() {
   return true;
}
    

Die Methode gibt immer true zurück . Lassen Sie uns dies in der Praxis testen.


public static void main(String[] args) {
   byte[] buf = {65, 66, 67, 68, 69};
   try (ByteArrayInputStream bais = new ByteArrayInputStream(buf)) {
       boolean isMarkSupported = bais.markSupported();

       System.out.println("isMarkSupported: " + isMarkSupported);
       System.out.println("Read: " + bais.read());
       System.out.println("Read: " + bais.read());

       bais.mark(1);
       System.out.println("Read: " + bais.read());
       isMarkSupported = bais.markSupported();
       System.out.println("isMarkSupported: " + isMarkSupported);

       bais.reset();
       isMarkSupported = bais.markSupported();
       System.out.println("isMarkSupported: " + isMarkSupported);
   } catch (IOException e) {
       e.printStackTrace();
   }
}
    

Nach der Ausführung der Methoden mark() und reset() ist unser Stream immer bereit und unterstützt Markierungen:

Ausgang:

isMarkSupported: true
Lesen: 65
Lesen: 66
Lesen: 67
isMarkSupported: true
isMarkSupported: true

schließen()

Und um die Close- Methode zu verstehen, werfen wir auch einen Blick hinein:


/**
* Closing a {@code ByteArrayInputStream} has no effect. The methods in
* this class can be called after the stream has been closed without
* generating an {@code IOException}.
*/
public void close() throws IOException {
}
    

Aus der Dokumentation der Methode close geht hervor, dass das Schließen eines ByteArrayInputStream keine Auswirkungen hat. Die Methoden der ByteArrayInputStream- Klasse können aufgerufen werden, nachdem der Stream geschlossen wurde, ohne eine IOException auszulösen .

Was können wir daraus schließen?

Wir benötigen einen ByteArrayInputStream , wenn wir Daten aus einem Byte-Array lesen möchten. Normalerweise ist es sinnvoll, diese Klasse in Kombination mit anderem Code zu verwenden, der weiß, wie man mit InputStreams arbeitet , und nicht allein.