creartion du ficheir BytesUtils.java
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
package fr.iutfbleu.sae.util;
|
||||
|
||||
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é
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package fr.iutfbleau.sae.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Décorateur de flux permettant la lecture binaire à granularité du bit.
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Utilisée notamment pour le décodage des fichiers compressés
|
||||
* (ex : format PIF utilisant des codes de Huffman).
|
||||
* </p>
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package fr.iutfbleau.sae.util;
|
||||
|
||||
/**
|
||||
* Classe utilitaire regroupant des opérations de conversion entre
|
||||
* entiers et octets.
|
||||
* <p>
|
||||
* Elle est utilisée pour encoder et décoder les champs binaires
|
||||
* du format PIF (largeur, hauteur, tailles, etc.).
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Cette classe :
|
||||
* <ul>
|
||||
* <li>ne lit aucun fichier</li>
|
||||
* <li>n'écrit aucun fichier</li>
|
||||
* <li>ne manipule pas les bits individuellement</li>
|
||||
* </ul>
|
||||
* Elle fournit uniquement des conversions octets ↔ entiers.
|
||||
* </p>
|
||||
*/
|
||||
public final class ByteUtils {
|
||||
|
||||
/**
|
||||
* Constructeur privé empêchant l'instanciation.
|
||||
* <p>
|
||||
* Cette classe est purement utilitaire et ne doit pas être instanciée.
|
||||
* </p>
|
||||
*/
|
||||
private ByteUtils() {
|
||||
// empêche l'instanciation
|
||||
}
|
||||
|
||||
/**
|
||||
* Convertit un entier non négatif en deux octets (ordre big-endian).
|
||||
* <p>
|
||||
* L'octet de poids fort est placé en première position,
|
||||
* suivi de l'octet de poids faible.
|
||||
* </p>
|
||||
*
|
||||
* @param value valeur entière à convertir (0 ≤ value ≤ 65535)
|
||||
* @return tableau de deux octets : [octetFort, octetFaible]
|
||||
* @throws IllegalArgumentException si la valeur ne tient pas sur 2 octets
|
||||
*/
|
||||
public static byte[] toBytes(int value) {
|
||||
if (value < 0 || value > 0xFFFF) {
|
||||
throw new IllegalArgumentException(
|
||||
"La valeur doit être comprise entre 0 et 65535"
|
||||
);
|
||||
}
|
||||
|
||||
byte[] result = new byte[2];
|
||||
|
||||
/*
|
||||
* Extraction de l'octet de poids fort :
|
||||
* - décalage de 8 bits vers la droite
|
||||
* - masquage pour ne conserver que les 8 bits utiles
|
||||
*/
|
||||
result[0] = (byte) ((value >>> 8) & 0xFF);
|
||||
|
||||
/*
|
||||
* Extraction de l'octet de poids faible :
|
||||
* - aucun décalage nécessaire
|
||||
* - masquage pour conserver les 8 bits de droite
|
||||
*/
|
||||
result[1] = (byte) (value & 0xFF);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstruit un entier à partir de deux octets (ordre big-endian).
|
||||
* <p>
|
||||
* L'octet de poids fort est replacé dans les bits 15 à 8,
|
||||
* puis combiné avec l'octet de poids faible.
|
||||
* </p>
|
||||
*
|
||||
* @param high octet de poids fort
|
||||
* @param low octet de poids faible
|
||||
* @return entier reconstruit à partir des deux octets
|
||||
*/
|
||||
public static int toInt(byte high, byte low) {
|
||||
/*
|
||||
* - masquage pour supprimer le signe des octets Java
|
||||
* - décalage de l'octet fort vers la gauche
|
||||
* - combinaison des deux octets par un OU binaire
|
||||
*/
|
||||
return ((high & 0xFF) << 8) | (low & 0xFF);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user