US-D1 et US-D2
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Décorateur de flux permettant l'écriture binaire à granularité du bit.
|
||||
* <p>
|
||||
* Cette classe encapsule un {@link OutputStream} existant et permet
|
||||
* l'écriture de bits individuellement ou par groupes.
|
||||
* Les bits sont accumulés afin de former des octets avant écriture.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Utilisée notamment pour l'encodage des fichiers compressés
|
||||
* (ex : format PIF utilisant des codes de Huffman).
|
||||
* </p>
|
||||
*/
|
||||
public class BitOutputStream {
|
||||
|
||||
/** Flux de sortie sous-jacent */
|
||||
private final OutputStream fluxSortie;
|
||||
|
||||
/** Octet en cours de construction */
|
||||
private int octetEnConstruction;
|
||||
|
||||
/** Position du prochain bit à écrire (de 7 à 0) */
|
||||
private int positionBit;
|
||||
|
||||
/** Indique si le flux est fermé */
|
||||
private boolean fluxFerme;
|
||||
|
||||
/**
|
||||
* Construit un écrivain binaire à partir d'un flux existant.
|
||||
*
|
||||
* @param fluxSortie flux de sortie à décorer
|
||||
* @throws IllegalArgumentException si le flux est nul
|
||||
*/
|
||||
public BitOutputStream(OutputStream fluxSortie) {
|
||||
if (fluxSortie == null) {
|
||||
throw new IllegalArgumentException("Le flux de sortie ne peut pas être nul");
|
||||
}
|
||||
this.fluxSortie = fluxSortie;
|
||||
this.octetEnConstruction = 0;
|
||||
this.positionBit = 7;
|
||||
this.fluxFerme = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Écrit un bit dans le flux binaire.
|
||||
*
|
||||
* @param bit bit à écrire (0 ou 1)
|
||||
* @throws IOException si une erreur d'écriture survient
|
||||
* @throws IllegalArgumentException si le bit n'est ni 0 ni 1
|
||||
*/
|
||||
public void writeBit(int bit) throws IOException {
|
||||
if (bit != 0 && bit != 1) {
|
||||
throw new IllegalArgumentException("Le bit doit être 0 ou 1");
|
||||
}
|
||||
if (fluxFerme) {
|
||||
throw new IOException("Le flux de sortie est fermé");
|
||||
}
|
||||
if (bit == 1) {
|
||||
this.octetEnConstruction = this.octetEnConstruction | (1 << this.positionBit);
|
||||
}
|
||||
this.positionBit--;
|
||||
|
||||
// si on atteint la fin de l'octet, on le grave dans le flux et rebolotte
|
||||
if(this.positionBit < 0){
|
||||
this.fluxSortie.write(this.octetEnConstruction);
|
||||
this.octetEnConstruction = 0;
|
||||
this.positionBit = 7;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Écrit une séquence de bits correspondant à une valeur entière.
|
||||
*
|
||||
* @param valeur valeur contenant les bits à écrire
|
||||
* @param nombreBits nombre de bits à écrire (strictement positif)
|
||||
* @throws IOException si une erreur d'écriture survient
|
||||
*/
|
||||
public void writeBits(int valeur, int nombreBits) throws IOException {
|
||||
for (int i = nombreBits - 1; i >= 0; i--) {
|
||||
int bit = (valeur >> i) & 1;
|
||||
writeBit(bit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force l'écriture immédiate des données accumulées dans le flux sous-jacent.
|
||||
*
|
||||
* @throws IOException si une erreur survient lors du flush
|
||||
*/
|
||||
public void flush() throws IOException {
|
||||
if (fluxFerme) {
|
||||
throw new IOException("Le flux de sortie est fermé");
|
||||
}
|
||||
while (this.positionBit >= 0) {
|
||||
writeBit(0);
|
||||
}
|
||||
this.fluxSortie.flush(); // Force l'écriture dans le flux sous-jacent
|
||||
}
|
||||
|
||||
/**
|
||||
* Vide les buffers internes et ferme le flux de sortie.
|
||||
*
|
||||
* @throws IOException si une erreur survient lors de la fermeture
|
||||
*/
|
||||
public void fermerFlux() throws IOException {
|
||||
// si le flux n'est pas déjà fermé
|
||||
if (!fluxFerme) {
|
||||
this.flush(); // compléter l'octet et forcer l'écriture
|
||||
this.fluxSortie.close(); // fermer le flux sous-jacent
|
||||
this.fluxFerme = true; // marquer le flux comme fermé
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user