package fr.iutfbleau.sae.util; import java.io.IOException; import java.io.InputStream; /** * Décorateur de flux permettant la lecture binaire à granularité du bit. *

* Cette classe encapsule un {@link InputStream} existant et fournit * des opérations de lecture bit par bit ou par groupes de bits. * Elle ne gère ni l'ouverture ni la sélection du fichier source. *

* *

* Utilisée notamment pour le décodage des fichiers compressés * (ex : format PIF utilisant des codes de Huffman). *

* * * * @author Algassimou Pellel Diallo * @version 1.0 * @since 2025-12-13 */ public class BitinputStream { /** Flux d'entrée sous-jacent */ private final InputStream fluxEntree; /** Octet actuellement chargé depuis le flux */ private int octetCourant; /** Position du bit courant dans l'octet (du bit 7 au bit 0) */ private int positionBit; /** Indique si la fin du flux a été atteinte */ private boolean finDeFlux; /** * Construit un lecteur binaire à partir d'un flux existant. * * @param fluxEntree flux d'entrée à décorer * @throws IllegalArgumentException si le flux est nul */ public BitinputStream(InputStream fluxEntree) { if (fluxEntree == null) { throw new IllegalArgumentException("Le flux d'entrée ne peut pas être nul"); } this.fluxEntree = fluxEntree; this.octetCourant = 0; this.positionBit = -1; // force la lecture d'un nouvel octet this.finDeFlux = false; } /** * Lit un bit depuis le flux binaire. * * @return 0 ou 1 si un bit est lu, -1 si la fin du flux est atteinte * @throws IOException si une erreur de lecture survient */ public int readBit() throws IOException { if (finDeFlux) { return -1; } if (this.positionBit < 0) { int octetLu = this.fluxEntree.read(); if (octetLu == -1) { this.finDeFlux = true; } else { this.octetCourant = octetLu; this.positionBit = 7; } } if (finDeFlux) { return -1; } int bit = (this.octetCourant >> this.positionBit) & 1; this.positionBit--; return bit; } /** * Lit une séquence de bits consécutifs et les assemble dans un entier. * * @param nombreBits nombre de bits à lire (strictement positif) * @return valeur entière correspondant aux bits lus, * ou -1 si la fin du flux est atteinte prématurément * @throws IOException si une erreur de lecture survient */ public int readBits(int nombreBits) throws IOException { int res=0; for (int i = 0; i < nombreBits; i++) { int bit = readBit(); if (bit == -1) { return -1; } res = (res << 1) | bit; } return res; } /** * Ferme le flux d'entrée sous-jacent. * * @throws IOException si une erreur survient lors de la fermeture */ public void closeFlux() throws IOException { this.fluxEntree.close(); } }