:: Enseignements :: Master :: M1 :: 2017-2018 :: Programmation d'applications réseaux ::
[LOGO]

Manipulation de base des buffers, jeux de caractères et endianness


Pour cette séance, nous vous fournissons File2Hex.jar qui permet d'afficher en hexadécimal les octets contenus dans un fichier passé en argument.
% java -jar File2Hex filename

Exercice 1 - Endianness

On souhaite écrire une classe StoreWithByteOrder qui lit des entiers long sur l'entrée standard et qui les écrit octet par octet dans un fichier. L'ordre (little endian ou big endian) d'écriture des octets dans le fichier doit être celui spécifié sur la ligne de commande par LE ou BE juste avant le nom du fichier.

Par exemple, les commandes
% java fr.upem.buffers.StoreWithByteOrder BE long-be.txt
1
^D
et
% java fr.upem.buffers.StoreWithByteOrder LE long-le.txt
1
^D
doivent produire deux fichiers différents. Pour savoir ce que contiennent ces fichiers, vous pouvez utiliser le jar File2Hex donné en début d'exercice.

Exercice 2 - Lecture d'un fichier comme un fichier texte avec encodage

On souhaite écrire une classe LoadWithEncoding qui accepte deux arguments sur la ligne de commande: le nom d'un jeu de caractères, et le nom d'un fichier. La fonction main doit alors afficher la chaîne correspondant aux octets du fichier dont le nom est fourni en second argument en utilisant l'encodage préconnisé en premier argument. Si un seul argument est donné alors la classe lira les octets sur l'entrée standard (jusqu'à trouver une fin de flot qui peut être donnée en tapant Control-D).

On va utiliser la méthode charset.decode() pour passer des octets à la chaîne de caractères correspondante. Expliquez pourquoi il est nécessaire d'avoir tous les octets du fichier avant d'appeler la méthode decode.

En partant du squelette LoadWithEncoding.java, complétez la méthode fileToString qui correspond au cas où deux paramètres sont donnés et où la lecture se fait dans un fichier. Vous pourrez obtenir la taille en octets du fichier en appelant la méthode fileChannel.size(). Attention: même si le buffer fait la même taille que le fichier, la méthode fileChannel.read() n'est pas garantie de remplir le buffer en un seul appel. Il faut donc l'appeler jusqu'à ce que le buffer soit plein (!buffer.hasRemaining()).

Vous pouvez tester votre programme avec le fichier test.txt
% java fr.upem.buffers.LoadWithEncoding utf8 test.txt
qui doit afficher:
a€
Alors que,
% java fr.upem.buffers.LoadWithEncoding iso-8859-1 test.txt
devrait afficher:
aâ ¬
Utilisez File2Hex pour comprendre cet affichage.

Complétez la méthode stringFromStandardInput qui correspond à la lecture sur l'entrée standard. On peut obtenir une ReadableByteChannel correspondant à l'entrée standard avec:
ReadableByteChannel in = Channels.newChannel(System.in);
Question 1.Une ReadableByteChannel se comporte comme un FileChannel en lecture sauf que l'on ne peut pas connaitre à l'avance la taille en octets. Il faudra donc lire dans un buffer de taille fixe et agrandir ce buffer quand il est plein. Pour agrandir, on créera un buffer deux fois plus grand et on copiera l'ancien buffer dans ce nouveau buffer. Pour copier la zone de travail d'un ByteBuffer src au début de la zone de travail d'un ByteBuffer dst, on utilise dst.put(src).