Clasa ByteArrayInputStream din pachetul java.io poate fi folosită pentru a citi o matrice de intrare (de octeți).

Pentru a crea un flux de intrare cu matrice de octeți, trebuie mai întâi să importam pachetul java.io.ByteArrayInputStream . După ce importăm pachetul, avem doi constructori disponibili pentru a crea un flux de intrare:

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

Există 4 câmpuri în interiorul clasei:

// 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;

Și iată constructorii noștri:

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

Metode ale clasei ByteArrayInputStream

Metodă Acțiune
int read() Citește următorul octet de date din acest flux de intrare.
int read(byte b[], int off, int len) Citește câțiva octeți din fluxul de intrare și îi stochează în matricea tampon b .
off este un offset în matricea țintă b .
len este numărul maxim de octeți de citit.
salt lung (n lung) Omite n octeți de intrare din acest flux de intrare. Returnează numărul de octeți săriți (poate fi mai mic de n dacă ajungem la sfârșitul fluxului de intrare).
int disponibil() Returnează numărul de octeți rămași care pot fi citiți (sau săriți) din acest flux de intrare.
void reset() Resetează tamponul la poziția marcată. Poziția marcată este 0, cu excepția cazului în care este marcată o altă poziție sau nu este specificat un offset diferit în constructor.
marca booleană acceptată () Verifică dacă acest InputStream acceptă marcarea/resetarea. Returnează adevărat pentru ByteArrayInputStream .
void close() Nu face nimic.
marcare nulă (int readAheadLimit) Seteazămarcăcâmp egal cu poziția curentă. Dacă este apelată metoda de resetare , citirea ulterioară va începe din acea poziție. Parametrul readAheadLimit nu este utilizat și nu afectează comportamentul metodei.

Să aruncăm o privire mai atentă la aceste metode și să vedem cum funcționează în practică.

citit()

Când doriți să citiți octeți dintr-un ByteArrayInputStream exact așa cum ați face dintr-un InputStream obișnuit , puteți utiliza metoda read() .

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

disponibil()

Dacă doriți să verificați dacă există ceva în tampon, puteți apela metoda available() .

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

Vom vedea că numărul de octeți disponibili pentru citire se modifică după fiecare citire din buffer.

Ieșire:

Octeți disponibili pentru citire: 4
octeți disponibili pentru citire: 3
octeți disponibili pentru citire: 2

sari peste (n lung)

Puteți folosi metoda skip() pentru a sări peste un anumit număr de octeți și pentru a nu le citi.

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

Ieșire:

3, 4,

reset()

Această metodă resetează poziția fluxului tamponat la ultima poziție marcată. Este poziţia 0, cu excepţia cazului în care este setat un alt marcaj.

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

Vom vedea că apelarea metodei reset() ne duce la punctul de pornire al fluxului nostru.

Ieșire:

Citire: 65
Citire: 66
Citire: 67
Citire: 68
Apelarea metodei reset()
Citire: 65
Citire: 66

marcare(int readAheadLimit)

Metoda mark() a clasei ByteArrayInputStream setează marcajul intern la poziția curentă a octetului, adică imediat după octetul citit anterior. Această metodă ia un parametru care indică câți octeți pot fi citiți după marcaj înainte ca fluxul să devină invalid. În mod implicit, dacă marcajul nu este setat în mod explicit, un ByteArrayInputStream marchează poziția 0 sau poziția offset-ului transmisă constructorului său. Este important de reținut că marcarea readAheadLimit este irelevantă pentru această clasă.

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

Iată un exemplu de setare a unui marcaj într-un ByteArrayInputStream folosind metodele sale mark() și reset() . Vom adăuga un apel la metoda mark() la exemplul anterior:

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

Putem vedea că poziția fluxului curent s-a schimbat.

Ieșire:

Citire: 65
Citire: 66
Citire: 67
Citire: 68
Citire: 69
Apelarea metodei reset()
Citire: 68
Citire: 69

markSupported()

Metoda markSupported() vă permite să verificați dacă un marcaj poate fi setat. Pentru a înțelege de unde vine valoarea returnată, să mergem la codul metodei:

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

Metoda returnează întotdeauna adevărat . Să testăm acest lucru în practică.

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

După executarea metodelor mark() și reset() , fluxul nostru este întotdeauna gata și acceptă marcaje:

Ieșire:

isMarkSupported: true
Citiți: 65
Citiți: 66
Citiți: 67
isMarkSupported: true
isMarkSupported: true

închide()

Și pentru a înțelege metoda apropiată , să aruncăm și o privire în ea:

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

Documentația pentru metoda close ne spune că închiderea unui ByteArrayInputStream nu are niciun efect. Metodele clasei ByteArrayInputStream pot fi apelate după ce fluxul este închis fără a arunca o IOException .

Ce putem concluziona?

Avem nevoie de un ByteArrayInputStream atunci când dorim să citim date dintr-o matrice de octeți. De obicei, are sens să utilizați această clasă în combinație cu alt cod care știe cum să lucreze cu InputStreams , mai degrabă decât de la sine.