De klasse ByteArrayInputStream in het pakket java.io kan worden gebruikt om een ​​invoerarray (van bytes) te lezen.

Om een ​​byte-array-invoerstroom te maken, moeten we eerst het java.io.ByteArrayInputStream- pakket importeren. Nadat we het pakket hebben geïmporteerd, hebben we twee constructors beschikbaar voor het maken van een invoerstroom:

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

Er zijn 4 velden binnen de 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;

En hier zijn onze constructeurs:

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 van de klasse ByteArrayInputStream

Methode Actie
int gelezen() Leest de volgende byte aan gegevens uit deze invoerstroom.
int lezen(byte b[], int uit, int len) Leest verschillende bytes uit de invoerstroom en slaat ze op in bufferarray b .
off is een offset in doelarray b .
len is het maximum aantal te lezen bytes.
lang overslaan(lange n) Slaat n bytes invoer van deze invoerstroom over. Retourneert het aantal overgeslagen bytes (dit kan minder zijn dan n als we het einde van de invoerstroom bereiken).
int beschikbaar() Retourneert het aantal resterende bytes dat kan worden gelezen (of overgeslagen) van deze invoerstroom.
nietig resetten() Reset de buffer naar de gemarkeerde positie. De gemarkeerde positie is 0, tenzij een andere positie is gemarkeerd of een andere offset is opgegeven in de constructor.
boolean markSupported() Controleert of deze InputStream markering/resetten ondersteunt. Retourneert true voor ByteArrayInputStream .
nietig sluiten() Doet niets.
ongeldig teken (int readAheadLimit) Stelt demarkeringveld gelijk aan de huidige positie. Als de reset- methode wordt aangeroepen, begint het volgende lezen vanaf die positie. De parameter readAheadLimit wordt niet gebruikt en heeft geen invloed op het gedrag van de methode.

Laten we deze methoden eens nader bekijken en zien hoe ze in de praktijk werken.

lezen()

Als u bytes wilt lezen van een ByteArrayInputStream , net zoals u dat zou doen van een gewone InputStream , kunt u de methode read() gebruiken .

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

beschikbaar()

Als u wilt controleren of er iets in uw buffer zit, kunt u de methode available() aanroepen.

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

We zullen zien dat het aantal beschikbare bytes voor lezen verandert na elke lezing uit de buffer.

Uitgang:

Bytes beschikbaar om te lezen: 4
Bytes beschikbaar om te lezen: 3
Bytes beschikbaar om te lezen: 2

overslaan(lange n)

U kunt de methode skip() gebruiken om een ​​bepaald aantal bytes over te slaan en deze niet te lezen.

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

Uitgang:

3, 4,

opnieuw instellen()

Deze methode zet de positie van de gebufferde stream terug naar de laatst gemarkeerde positie. Het is positie 0 tenzij een andere markering is ingesteld.

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

We zullen zien dat het aanroepen van de methode reset() ons naar het startpunt van onze stream brengt.

Uitgang:

Lezen: 65
Lezen: 66
Lezen: 67
Lezen: 68
Reset()-methode aanroepen
Lezen: 65
Lezen: 66

mark(int readAheadLimit)

De methode mark() van de klasse ByteArrayInputStream stelt de interne markering in op de huidige bytepositie, dat wil zeggen direct na de eerder gelezen byte. Deze methode gebruikt een parameter die aangeeft hoeveel bytes na de markering kunnen worden gelezen voordat de stream ongeldig wordt. Als de markering niet expliciet is ingesteld, markeert een ByteArrayInputStream standaard positie 0 of de positie van de offset die aan de constructor is doorgegeven. Het is belangrijk op te merken dat de readAheadLimit- markering niet relevant is voor deze klasse.

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

Hier is een voorbeeld van het instellen van een markering in een ByteArrayInputStream met behulp van de methoden mark() en reset() . We zullen een aanroep toevoegen aan de methode mark() aan het vorige voorbeeld:

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

We kunnen zien dat de positie van de huidige stream is veranderd.

Uitgang:

Lezen: 65
Lezen: 66
Lezen: 67
Lezen: 68
Lezen: 69
Reset()-methode aanroepen
Lezen: 68
Lezen: 69

markSupported()

Met de methode markSupported() kunt u controleren of een markering kan worden ingesteld. Om te begrijpen waar de geretourneerde waarde vandaan komt, gaan we naar de code van de 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;
}

De methode retourneert altijd true . Laten we dit in de praktijk 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();
   }
}

Na het uitvoeren van de methoden mark() en reset() is onze stream altijd gereed en ondersteunt deze marks:

Uitgang:

isMarkSupported: true
Lezen: 65
Lezen: 66
Lezen: 67
isMarkSupported: true
isMarkSupported: true

dichtbij()

En om de close- methode te begrijpen, laten we er ook een kijkje in nemen:

/**
* 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 {
}

De documentatie voor de methode close vertelt ons dat het sluiten van een ByteArrayInputStream geen effect heeft. De methoden van de klasse ByteArrayInputStream kunnen worden aangeroepen nadat de stream is gesloten zonder een IOException te genereren .

Wat kunnen we concluderen?

We hebben een ByteArrayInputStream nodig als we gegevens uit een byte-array willen lezen. Het is meestal logisch om deze klasse te gebruiken in combinatie met andere code die weet hoe hij met InputStreams moet werken in plaats van op zichzelf.