C. Recanati InHM Java Master 1, 2007-2008 TP 3 Rappels sur les flots d’entrées: Les opérations de flots d’entrée d’octets sont définies par des sous-classes de la classe abstraite InputStream, et celles sur les flots d’entrée de caractères par des sous-classes de Reader La classe System de java.lang définit les membres in, out et err (de type PrintStream) pour représenter respectivement le flot d’entrée standard et les flots de sortie standard et d’erreur standard On peut utiliser la classe StreamTokenizer pour lire des données formatées à partir d’un flot Exercice 1 Pour pouvoir lire facilement des caractères, des entiers ou des réels sur le flot d’entrée standard System.in, écrire une classe In qui permettra : - d'initialiser le flot d'entrée avec une méthode init() ; - de tester le flot d’entrée avec une méthode isEmpty() ; - de lire des données formattées sur le flot d’entrée avec des méthodes getString(), getDouble() et getInt(). Pour l’implémentation de ces méthodes, la classe In possèdera en outre : - un champ privé statique de type int permettant de stocker le dernier caractère lu sur le flot des entrées standard, - une procédure readC permettant de lire un nouveau caractère sur le flot d’entrée - et une méthode privée booléenne permettant de savoir si le caractère lu est un caractère blanc. import java.io.*; public class In { private static int c; private static boolean isWhite() { return Character.isWhiteSpace ( (char) c); } private static void readC () { try { c = System.in.read(); } catch (IOException e) {c = -1;} } ... } Rappels sur les sorties des types élémentaires de données vers un flot : Un chemin d’accès à un fichier peut être représenté par un objet de la classe File et un fichier physique peut être représenté par un objet du type FileDescriptor Les opérations sur les flots d’octets génèrent des flots contenant des octets (sans conversion) et les opérations sur les flots de caractères génèrent des flots qui contiennent des caractères dans le code de caractères de la machine locale Les flots de sortie d’octets sont représentés par des sousclasses de la classe abstraite OutputStream. Ces classes permettent d’écrire vers un fichier Les flots de sortie de caractères sont représentés par des sousclasses de la classe abstraite Writer En outre : Les classes de flots de sortie filtrés peuvent être utilisées pour améliorer les fonctionnalités des classes de flots de sortie de base qui représentent un fichier physique Les classes de flots d’entrée filtrés complètent les classes de flots de sortie filtrés Si vous souhaitez formater les données que vous écrivez dans un flot, vous devez mettre en œuvre vous-même une fonction de formatage Exercice 2 Sorties binaires : la classe FileOutputStream. Ecrire un programme qui crée un objet File à partir d’un chemin d’accès, puis, après avoir vérifié qu’aucun fichier de ce nom n’existe, crée un objet FileOutputStream à partir de ce File (nouveau fichier) pour écrire dedans (si ce fichier n’existait pas...). Utiliser exists() et createNewFile() et traiter les IOException par une impression sur la sortie standard. Exercice 3 Sorties binaires : la classe DataOutputStream. Ecrire une classe TestFlotDeDonnees qui crée un répertoire à partir d’un chemin (String) s’il n’existe pas, quitte le programme si ce chemin correspond à un fichier qui n’est pas un répertoire, et sinon crée un fichier nommé « donnees.txt » dans ce répertoire (à condition que ce fichier n’existe pas déjà). Le programme va alors écrire dans ce fichier la chaîne de caractères « Donnees inutilisables entrantes et sortantes ». Le programme traitera les exceptions (de type IOException ) et les imprimera si elles se produisent. On imprimera également la taille en octets du flot DataOutputStream représentant le fichier en utilisant la méthode size(). [Remarque : On doit constater que si la chaîne initiale contient n caractères - ces caractères étant des caractères Unicode (codés sur 16 bits) - ils occupent alors 2n octets]. 1. Pour créer un DataOutputStream permettant d’écrire dans un fichier, on crée d’abord un objet File, puis un objet FileOutputStream à partir de l’objet File, puis un objet DataOutputStream à partir de l’objet FileOutputStream . 2. Pour écrire une chaîne String dans le flot de sortie, on dispose de la méthode writeChars() qui accepte un argument de type String. Correction Exercice 1 import java.io.*; public class In { private static int c; ... // voir énoncé de l’exo plus haut public static void init() { readC(); } public static boolean isEmpty() { return c == -1; } public static String getString () { String s = ""; while (!(isEmpty() || isWhite() )) { s += (char) c; readC (); } while (!(isEmpty() || isWhite() )) return s; } public static int getInt() { return Integer.parseInt(getString()); } public static double getDouble () { return Double.parseDouble(getString()); } } Exercice 2: String filename = « monFichier.txt » ; File unFichier = new File(nomFichier) ; try { if ( ! unFichier.exists () ) { // créer un nouveau fichier unFichier.createNewFile() ; FileOutputStream file1 = new(FileOutputStream(unFichier)) ; System.out.println(« Flot de sortie sur \ monFichier.txt créé ») ; } else System.out.println(«monFichier.txt existe déjà») ; } catch (IOException e) { System.out.println(e) ; } Exercice 3: import java.io.* ; import java.util.Date; public class TestFlotDeDonnees { public static void main (String [ ] args ) { String maChaine = new String (« Donnees inutilisables \ entrantes et sortantes ») ; String nomRepertoire = « xxx/MesDonnees » ; try { File rep = new File (nomRepertoire) ; if ( !rep.exists()) // si le repertoire n’existe pas rep.mkdir() ; // le créer else if ( !rep.isDirectory()) { System.err.println (nomRepertoire + «n’est pas un repertoire») ; return ; } File unFichier = new File(rep,«donnees.txt»); unFichier.createNewFile() ; DataOutputStream monFlotDeDonnees = new DataOutputStream ( new FileOutputStream(unFichier)) ; monFlotDeDonnees.writeChars(maChaine) ; } catch (IOException e) { System.out.println («IOException levee:» + e) ; } } }