La classe ByteArrayInputStream du package java.io peut être utilisée pour lire un tableau d'entrée (d'octets).

Pour créer un flux d'entrée de tableau d'octets, nous devons d'abord importer le package java.io.ByteArrayInputStream . Après avoir importé le package, nous avons deux constructeurs disponibles pour créer un flux d'entrée :

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

Il y a 4 champs à l'intérieur de la classe :

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

Et voici nos 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;
}

Méthodes de la classe ByteArrayInputStream

Méthode Action
entier lu() Lit l'octet de données suivant à partir de ce flux d'entrée.
int lire (octet b [], int off, int len) Lit plusieurs octets du flux d'entrée et les stocke dans le tableau tampon b .
off est un décalage dans le tableau cible b .
len est le nombre maximum d'octets à lire.
long saut (long n) Ignore n octets d'entrée de ce flux d'entrée. Renvoie le nombre d'octets ignorés (il peut être inférieur à n si nous atteignons la fin du flux d'entrée).
int disponible() Renvoie le nombre d'octets restants pouvant être lus (ou ignorés) à partir de ce flux d'entrée.
annuler la réinitialisation() Réinitialise le tampon à la position marquée. La position marquée est 0 sauf si une autre position est marquée ou si un décalage différent est spécifié dans le constructeur.
marque booléenneSupported() Vérifie si cet InputStream prend en charge le marquage/la réinitialisation. Renvoie true pour ByteArrayInputStream .
annuler fermer() Ne fait rien.
marque vide (int readAheadLimit) Définit lemarquerchamp égal à la position actuelle. Si la méthode de réinitialisation est appelée, la lecture suivante commencera à partir de cette position. Le paramètre readAheadLimit n'est pas utilisé et n'affecte pas le comportement de la méthode.

Examinons de plus près ces méthodes et voyons comment elles fonctionnent dans la pratique.

lire()

Lorsque vous souhaitez lire des octets à partir d'un ByteArrayInputStream comme vous le feriez à partir d'un InputStream ordinaire , vous pouvez utiliser la méthode 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();
   }
}

disponible()

Si vous voulez vérifier s'il y a quelque chose dans votre tampon, vous pouvez appeler la méthode 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();
   }
}

Nous verrons que le nombre d'octets disponibles pour la lecture change après chaque lecture du tampon.

Sortir:

Octets disponibles en lecture : 4
Octets disponibles en lecture : 3
Octets disponibles en lecture : 2

sauter (n long)

Vous pouvez utiliser la méthode skip() pour ignorer un certain nombre d'octets et ne pas les lire.

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

Sortir:

3, 4,

réinitialiser()

Cette méthode réinitialise la position du flux mis en mémoire tampon à la dernière position marquée. C'est la position 0 à moins qu'une marque différente ne soit définie.

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

Nous verrons que l'appel de la méthode reset() nous amène au point de départ de notre flux.

Sortir:

Lecture : 65
Lecture : 66
Lecture : 67
Lecture : 68
Appel de la méthode reset()
Lecture : 65
Lecture : 66

marque(int readAheadLimit)

La méthode mark() de la classe ByteArrayInputStream définit la marque interne à la position actuelle de l'octet, c'est-à-dire immédiatement après l'octet lu précédemment. Cette méthode prend un paramètre qui indique combien d'octets peuvent être lus après la marque avant que le flux ne devienne invalide. Par défaut, si la marque n'est pas définie explicitement, un ByteArrayInputStream marque la position 0 ou la position du décalage passé à son constructeur. Il est important de noter que la marque readAheadLimit n'est pas pertinente pour cette classe.

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

Voici un exemple de définition d'une marque dans un ByteArrayInputStream à l'aide de ses méthodes mark() et reset() . Nous allons ajouter un appel à la méthode mark() à l'exemple précédent :

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

Nous pouvons voir que la position du flux actuel a changé.

Sortir:

Lecture : 65
Lecture : 66
Lecture : 67
Lecture : 68
Lecture : 69
Appel de la méthode reset()
Lecture : 68
Lecture : 69

markSupported()

La méthode markSupported() vous permet de vérifier si une marque peut être définie. Pour comprendre d'où vient la valeur de retour, passons au code de la méthode :

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

La méthode renvoie toujours true . Testons cela dans la pratique.

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

Après avoir exécuté les méthodes mark() et reset() , notre flux est toujours prêt et prend en charge les marques :

Sortir:

isMarkSupported : vrai
Lecture : 65
Lecture : 66
Lecture : 67
isMarkSupported : vrai
isMarkSupported : vrai

fermer()

Et pour comprendre la méthode close , jetons également un coup d'œil à l'intérieur :

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

La documentation de la méthode close nous indique que la fermeture d'un ByteArrayInputStream n'a aucun effet. Les méthodes de la classe ByteArrayInputStream peuvent être appelées après la fermeture du flux sans lever une IOException .

Que pouvons-nous conclure ?

Nous avons besoin d'un ByteArrayInputStream lorsque nous voulons lire des données à partir d'un tableau d'octets. Il est généralement logique d'utiliser cette classe en combinaison avec un autre code qui sait comment fonctionner avec InputStreams plutôt que par lui-même.