Table des matières

TD7 - Gestion des entrées-sorties

Lors de la séance précédente, vous avez implémenté des méthodes de compression et de décompression sur des chaînes de caractères. Nous allons maintenant mettre en œuvre une version plus générique travaillant directement sur des flux. Si jamais vous n’êtes pas parvenu à implémenter correctement la compression lors de la séance précédente, nous vous donnons, à la fin du sujet, un algorithme possible.

Travail à réaliser

Modifiez les fonctions de compression et de décompression pour qu’elles écrivent leur résultat dans un flux plutôt que de retourner une chaîne de caractères. La nouvelle interface ICompression est la suivante :

interface ICompression {
    public void compress(String data, Writer out) throws IOException;
    public void uncompress(String data, Writer out) throws IOException, RLEException;
}

Modifiez les fonctions compress et uncompress de la séance précédente pour qu’elles s’expriment à partir des nouvelles versions ci-dessus. Modifiez le programme de test pour que le résultat produit soit écrit dans un fichier. Pour rappel, la manipulation d’un flux texte sur un fichier se fait de la manière suivante :

BufferedReader in = new BufferedReader(new FileReader("foo.in"));
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));

Version entièrement basée sur les flux

Modifiez l’interface ICompression pour que nos deux fonctions ne manipulent plus que des flux. La nouvelle interface sera la suivante :

interface ICompression {
    public void compress(Reader data, Writer out) throws IOException;
    public void uncompress(Reader data, Writer out) throws IOException, RLEException;
}

Vous pourrez dans un premier temps lire le contenu du flux en entrée pour construire une chaîne de caractères et utiliser les fonctions précédentes. Modifiez ensuite votre implémentation pour directement travailler sur des flux, sans construire de chaîne intermédiaire.

Remarques

Générons une documentation

Pour que d’autres puissent utiliser notre bibliothèque de compression, nous devons produire une documentation de celle-ci. Il existe en Java un système de génération de la documentation des programmes appelé javadoc. Après avoir pris connaissance de la documentation sur javadoc et de son utilisation dans Eclipse, modifiez votre code en conséquence.

Pour aller plus loin

Pour l’instant, nous avons codé le nombre de répétitions sur un seul chiffre, ce qui rend le codage peu efficace. Par exemple, la chaîne composée de 17 fois le caractère ‘a’ est codé par a#9a#8.

Comme le nombre de répétitions après le flag est forcément supérieur strictement à 3 (sinon la chaîne après compression serait plus longue qu’avant compression), nous pouvons utiliser les valeurs de 0 à 3 pour indiquer des codages spéciaux qui seront plus efficaces. Par exemple, si # est le caractère flag :

Indications : algorithme de compression.

Au cas où vous auriez eu du mal à coder l’algorithme de compression, nous vous donnons ici en pseudo-code une solution possible. Notez bien que ce n’est PAS la seule solution possible, d’autres algorithmes sont possibles. Pour simplifier, nous supposerons que le flag est #.

String compress(String input) {
	String result = "";
	if (length(input) == 0) return "";
	char currentChar;
	int currentPos = 0;
	int repetitionCount;

	WHILE(currentPos < length(input)){
		repetitionCount = 0;
		currentChar = input(currentPos);
		WHILE((currentPos < length(input)) AND input(currentPos) == currentChar){
			repetitionCount = repetitionCount + 1;
			currentPos = currentPos + 1;
		}
		IF(currentChar == flag){
			REPEAT(repetitionCount){
				result = result + flag + "0";
			}
		}
		ELSE {
			WHILE(repetitionCount >0){
				IF(repetitionCount <= 3){
					REPEAT(repetitionCount){
						result = result + currentChar;
					}
				}
				ELSE{
					IF(repetitionCount >=9){
						result = result + currentChar + flag + "9";
					}
					ELSE{
						result = result + currentChar + flag + repetitionCount;
					}
				}
				repetitionCount = repetitionCount - 9;
			}
		}
	}
	return result;

}