Lire un flux bit à bit, c’est possible

Si vous avez déjà eu à lire un fichier SWF à la main (par exemple), vous aurez remarqué que, dans certains cas, il peut être nécessaire de lire un flux de données bit à bit. Alors, oui… Certains diront qu’il existe déjà des librairies pour parser un fichier SWF correctement, et qu’on a donc pas besoin de s’occuper de tout ça. Mais quand on veut juste lire deux valeurs dans l’entête, c’est un peu con dommage de devoir se farcir un jar supplémentaire et généralement lourd dans son projet.

D’où l’idée d’avoir une classe de lecture d’un flux de données bit à bit. Seulement voila…. Les classes du JDK ne proposent, au mieux, que la lecture octet par octet. Du coup, comment faire?

Et bien, c’est simple : l’idée est d’étendre la classe FilterInputStream pour lire un octet et le garder en mémoire avec un pointeur sur le bit actuellement lu de cet octet. A l’aide d’opérations binaires, il est alors très simple de récupérer le bit recherché.

Concrètement, la partie permettant de lire un seul bit ressemblera donc à ça :


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public int readBit() throws IOException {
    if (bitsCountLeft == 0) {
        bitsLeft = super.read();
        bitsCountLeft = 8;

        if (bitsLeft < 0) {
            bitsCountLeft = 0;
            return -1;
        }
    }
    return (bitsLeft & mask(--bitsCountLeft)) >> bitsCountLeft;
}

private static byte mask(int bitNumber) {
    if (bitNumber < 0 || bitNumber > 8) {
        throw new IllegalArgumentException();
    }
    return (byte) Math.pow(2, bitNumber);
}

Et pour le projet complet, ça se passe ici : https://github.com/excilys/BitInputStream

VN:R_U [1.9.22_1171]
Rating: 0 (from 0 votes)
Share
Ce contenu a été publié dans Java, avec comme mot(s)-clef(s) , , , . Vous pouvez le mettre en favoris avec ce permalien.

6 réponses à Lire un flux bit à bit, c’est possible

  1. Damien V. dit :

    Et comme l’a suggéré un certain Frédéric, le masque peut être judicieusement remplacé par : 1 << bitNumber

    VN:R_U [1.9.22_1171]
    Rating: 0 (from 0 votes)
  2. mgrenonville@excilys.com dit :

    Juste une petite remarque pour chipoter qui me vient de l’électronique : Un bit représente un bit. Un Integer (en java) en représente 32… Donc la signature me perturbe. Ou me fait penser à du C, au choix. Nous avons la chance d’avoir “boolean” pour représenter un bit ;)

    Pourquoi ne pas avoir mis :

    1
    public boolean readBit() throws IOException

    Ceci-dit, bien joué ;)

    VN:R_U [1.9.22_1171]
    Rating: 0 (from 0 votes)
  3. Damien V. dit :

    Utiliser un boolean comme type de retour imposait de renvoyer une exception pour notifier la fin du flux. En utilisant un type numérique, on peut garder le système utilisé dans InputStream.read() et renvoyer -1 une fois arrivé à la fin du flux.

    Au passage, j’ai longuement hésité entre l’utilisation d’un byte ou d’un int en valeur de retour. Mais finalement, je me suis dit que les opérations binaires devant être faites en int, et la mémoire étant largement suffisante (bouuuh, mauvaise excuse je sais :D) de nos jour, un int irait très bien :)

    VN:R_U [1.9.22_1171]
    Rating: 0 (from 0 votes)
    • mgrenonville@excilys.com dit :

      Bien vu ! Et Boolean ? (je sais, je m’accroche au boolean !)

      Il est vrai que par convention, on renvoie -1 pour signaler la fin du fichier. Encore une habitude de C. Enfin, c’est pas dit que null soit une meilleure idée… Bon, reste plus qu’a rajouter à Boolean une nouvelle valeur : Z (haute impédance)

      Qui a dit que l’électronique était une histoire de 0 et de 1 ?

      VN:R_U [1.9.22_1171]
      Rating: 0 (from 0 votes)

Laisser un commentaire