Master Réseaux et Systèmes Distribués (RSD) Algorithmique des systèmes et applications réparties (pré requis) Badr Benmammar [email protected] Plan - Pré requis Exception Capturer une exception : try … catch Propager une exception : throws Propager et capturer : throws et try … catch Générer une exception : throw Générer et capturer une exception : throw et try … catch Exceptions personnalisées : générer et capturer ses propres exceptions Gestion des fichiers Classe File Quelques flots : FileReader : lire un fichier caractère par caractère FileWriter : écrire des caractères dans un fichier PrintWriter : println et print dans un fichier BufferedReader : rechercher un mot dans un fichier Sérialisation : enregistrer et restaurer des objets L’interface Serializable ObjectOuputStream : écrire des objets dans un fichier ObjectInputStream : lire des objets à partir d’un fichier 2 Exception 3 Exception public class Equation1 { private int a, b; public Equation1(int a, int b) { java Equation1 0 2 this.a=a; this.b=b; } 0*X=2 public void afficher() { Exception in thread "main" System.out.println(a+" * X = "+b); java.lang.ArithmeticException: / by zero } at Equation1.solution(Equation1.java:10) int solution() { at Equation1.main(Equation1.java:17) return b/a; // ligne 10 } public static void main(String args[]) { int valeurA=Integer.valueOf(args[0]).intValue(); int valeurB=Integer.valueOf(args[1]).intValue(); Equation1 equa = new Equation1(valeurA,valeurB); equa.afficher(); int x = equa.solution();// ligne 17 System.out.println("résultat : X = "+x); } 4 } Exception L'instruction division entière peut lever une exception: ArithmeticException (erreur d'exécution) . Une exception est un message envoyé lors d'une erreur à l'exécution. Ce message contient des informations sur l'erreur qui s'est produite. Java stoppe l'exécution du code là où l'exception a été levée et envoie le "message" exception. Sans capture du message exception, celui provoque l'arrêt successif des méthodes appelées jusqu'à la machine JVM qui vous indique l'erreur produite avec beaucoup de détails issus des informations du message. Les exceptions sont organisées en classe, Java contient une classe nommée Exception, où sont répertoriés différents cas d'erreurs. 5 Capturer une exception public void afficher() { public class Equation2 { System.out.println(a+" * X = "+b); private int a, b; } public static void main(String args[]) { int solution( ) { int valeurA= int x; Integer.valueOf(args[0]).intValue(); try { int valeurB= x = b/a; Integer.valueOf(args[1]).intValue(); } catch (ArithmeticException e) { Equation2 equa = x = -1; new Equation2(valeurA,valeurB); L'instruction "try ... catch" permet de capturer des exceptions : dès qu'une equa.afficher(); exception est levée dans le corps }de try, le traitement de ce corps est return x; terminé. int x = equa.solution(); catch définit le "+x); traitement pour les} ArithmeticException capturées. System.out.println("résultat :X= } en reprenant après le bloc try-catch. L'exécution continue normalement } Ce mécanisme permet de traiter lesEXECUTION: erreurs et d'empêcher qu'elle n'arrête public Equation2(int a, int b) { l'application en cours. this.a=a; this.b=b; java Equation2 0 2 L'exception a été capturée et traitée :0x*=X-1. } =2 résultat : X = -1 6 Propager une exception public class Equation3 { private int a, b; public Equation3(int a, int b) { this.a=a; this.b=b; } public void afficher() { System.out.println(a+" * X = "+b); } int solution() throws ArithmeticException { return b/a; } public static void main(String args[]) { int valeurA= Integer.valueOf(args[0]).intValue(); int valeurB= Integer.valueOf(args[1]).intValue(); Equation3 equa = new Equation3(valeurA,valeurB); equa.afficher(); int x = equa.solution(); System.out.println("résultat : X = "+x); } } 7 Propager et capturer une exception public static void main(String args[]) { int valeurA= public class Equation3 { Integer.valueOf(args[0]).intValue(); private int a, b; public Equation3(int a, int b) { int valeurB= this.a=a; Integer.valueOf(args[1]).intValue(); this.b=b; Equation3 equa = new } Equation3(valeurA,valeurB); public void afficher() { equa.afficher(); System.out.println(a+" La déclaration "throws" la méthode est susceptible de lever une * X permet = "+b);d'indiquer que try { pas par un try-catch. exception : ici ArithmeticException, qu'elle ne capture } solution() throws ArithmeticException { à la méthode int x = equa.solution(); int ArithmeticException sera propagée/transmise appelante si elle est levée, donc il faut return que lesb/a; méthodes qui appelle la méthode solution mettent éventuellement: Xen=place System.out.println("résultat "+x); un } mécanisme de capture try-cath ou qu'elles propagent} elles l'exception. catchaussi (ArithmeticException e) { L'exception ArithmeticException peut survenirSystem.out.println dans la méthode ("pas solution puisque sa de solution"); déclaration l'indique (throws). } Lorsqu'elle survient dans solution, elle est propagée jusqu'à une méthode appelante qui la } capture et la traite. C'est la méthode main. } 8 (Générer/lever) une exception public class Equation4 { private int a, b; public Equation4(int a, int b) { this.a=a; this.b=b; } public void afficher() { System.out.println(a+" * X = "+b); } int solution() { if (a==0) throw new ArithmeticException ("division entière par zéro"); else return b/a; } public static void main(String args[]) { int valeurA=Integer.valueOf(args[0]).intValue(); int valeurB=Integer.valueOf(args[1]).intValue(); Equation4 equa = new Equation4(valeurA,valeurB); equa.afficher(); int x = equa.solution(); System.out.println("résultat : X = "+x); } } 9 (Générer/lever) une exception L'instruction "throw" (sans s) permet de générer/lever une exception, ici ArithmeticException. De plus, un message d'erreur est ajoutée dans les informations véhiculées par l'exception. Exception in thread "main" java.lang.ArithmeticException: division entière par zéro at Equation4.solution(Equation4.java:10) at Equation4.main(Equation4.java:18) L'instruction throw instancie un objet exception, arrête l'exécution normale des instructions et sauf try-catch propage l'exception. 10 Générer et capturer une exception public static void main(String args[]) { public class Equation4 { int valeurA= private int a, b; Integer.valueOf(args[0]).intValue(); public Equation4(int a, int b) { int valeurB= this.a=a; this.b=b; Integer.valueOf(args[1]).intValue(); } Equation4 equa = new public void afficher() { Equation4(valeurA,valeurB); System.out.println(a+" * X = "+b); equa.afficher(); } try { int solution() { int x = equa.solution(); A laArithmeticException capture d'exception, il est possible d'afficher le message associé if (a==0) throw new System.out.println("résultat : X = "+x); en utilisant la méthode getMessage sur l'objet exception. ("division entière par zéro"); e) { getMessage est une des méthodes }decatch l'objet(ArithmeticException Exception qui donne des else return b/a; System.out.println (e.getMessage()); informations sur l'exception. } } Exécution: } java Equation4 0 4 } 0*X=4 division entière par zéro 11 throws vs throw throws: ce mot clé permet d’ajouter à une déclaration de méthode qu'une exception potentielle sera propagée. Ce mot clé est suivi du nom de la classe qui va gérer l'exception. Ceci a pour but de définir le type d'exception qui risque d'être générée par l'instruction, ou la classe qui précède le mot clé throws. throw: celui-ci permet d'instancier un objet dans la classe suivant l'instruction throws. Cette instruction est suivie du mot clé new ainsi que d'un objet cité avec throws. En fait, il lance une exception, tout simplement. 12 Exception : résumé JVM main m2 Générer throws m1 throws try … catch throw throw try … catch try … catch Capturer: try … catch Propager : throws Propager et capturer: throws et try … catch Générer: throw Générer et capturer: throw et try … catch 13 Exceptions personnalisées public static void main(String args[]) { public class Enseignant { private String nom; System.out.println("Donner un nom:"); private int nombreh; String nom=Saisie.litexte(); public Enseignant (String nom, int System.out.println("Donner le nombre d'heures:"); nombreh) int nombreh = Saisie.litentier(); throws nombre try { { if (nombreh < 0) Enseignant en = new Enseignant(nom,nombreh); throw new nombre ( ); en.afficher ( ); else{ } catch (nombre e) { this.nom=nom; System.out.println("Attention!!"); this.nombreh=nombreh; } } System.out.println("FIN");} } public void afficher(){ System.out.println(nom+" " +nombreh+ " heures"); public class nombre extends Exception{ } public nombre ( ){ Objectif: obtenir des messages System.out.println ("LE NOMBRE D'HEURES EST d'erreurs appropriés à son NEGATIF!"); programme (générer et capturer 14 ses propres exceptions). }} Exceptions personnalisées public static void main(String args[]) { System.out.println("Donner un nom:"); String nom=Saisie.litexte(); Exécution: System.out.println("Donner le nombre d'heures:"); Sans exception (nombreh >=0) int nombreh = Saisie.litentier(); bb 77 heures try { FIN Enseignant en = new Enseignant(nom,nombreh); en.afficher ( ); Avec exception (nombreh <0) LE NOMBRE D'HEURES EST NEGATIF! } catch (nombre e) { System.out.println("Attention!!"); Attention!! } FIN System.out.println("FIN");} 15 Exceptions personnalisées public static void main(String args[]) { public class Enseignant { private String nom; System.out.println("Donner un nom:"); private int nombreh; String nom=Saisie.litexte(); public Enseignant (String nom, int System.out.println("Donner le nombre d'heures:"); nombreh) int nombreh = Saisie.litentier(); throws nombre, nom try { { if (nombreh < 0) Enseignant en = new Enseignant(nom,nombreh); throw new nombre ( ); en.afficher ( ); if (nom.equals ("")) } catch (nombre e) { throw new nom(); System.out.println("Attention!!"); else{ } this.nom=nom; catch (nom e) { this.nombreh=nombreh; } System.out.println ("Attention!!"); } } public void afficher(){ System.out.println("FIN"); System.out.println(nom+" " } +nombreh+ " heures"); public class nom extends Exception{ } public nom ( ){ 16 System.out.println ("LE NOM EST VIDE!");}} Exceptions personnalisées Exécution: Sans exception (nom.equals ("") == false) bb 77 heures FIN Avec exception (nom.equals ("") == true) LE NOM EST VIDE! Attention!! FIN public static void main(String args[]) { System.out.println("Donner un nom:"); String nom=Saisie.litexte(); System.out.println("Donner le nombre d'heures:"); int nombreh = Saisie.litentier(); try { Enseignant en = new Enseignant(nom,nombreh); en.afficher ( ); } catch (nom e) { System.out.println("Attention!!"); } System.out.println("FIN");} 17 Gestion des fichiers 18 Gestion des fichiers : classe File import java.io.*; public class Fichier extends File { public Fichier (String nomFichier) { super (nomFichier); } public boolean lirePossible() { return (this.exists()&&this.isFile() &&this.canRead()); } public boolean ecrirePossible() { return (this.exists()&&this.isFile() &&this.canWrite()); } public String proprietes() { StringBuffer s=new StringBuffer(); if (!this.exists()) s.append ("fichier non existant"); else if (this.isFile()) { s.append ("fichier"); if (this.canRead()) s.append (" acces en lecture"); if (this.canWrite()) s.append (" acces en ecriture"); } else if (this.isDirectory()) s.append ("repertoire"); return new String(s); } public String parent() { String nomAbsolu=this.getAbsolutePath(); return nomAbsolu.substring(0, nomAbsolu.lastIndexOf(File.separator)); } } Avec "/C/Rep/test" comme chemin absolu, le parent est /C/Rep 19 Gestion des fichiers : classe File Classe Fichier : Permet d'instancier un objet File par le nom (chemin relatif ou absolu) de ce fichier ou répertoire. Permet de savoir si le fichier est accessible en lecture ou écriture. Donne les caractéristiques du fichier ou répertoire. Classe File du package io : Méthodes : boolean exists si le fichier ou répertoire existe. boolean isFile si c'est un fichier. boolean canRead s'il est accessible en lecture. boolean canWrite s'il est accessible en écriture. boolean isDirectory si c'est un répertoire. String getName son nom sans le chemin d'accès. String getAbsolutePath son chemin absolu. Attribut static : separator le séparateur dans les chemins du système de fichier. 20 Un programme qui liste les propriétés des fichiers passés en argument import java.io.*; public class Fichier1 { public static void main(String[] args) { Fichier fichier; if (args.length==0) { System.out.println (" pas d’arguments ...!"); System.exit(0); } for (int i=0; i<args.length; ++i) { fichier= new Fichier (args[i]); System.out.println(fichier.getName()+" :"); System.out.println(fichier.proprietes()); } System.out.println("Le repertoire parent est :"); fichier=new Fichier (args[0]); System.out.println(fichier.parent()); } } Exécution: java Fichier1 f1.txt f2.java test f1.txt : fichier acces en lecture f2.java : fichier non existant test : fichier acces en lecture acces en ecriture Le repertoire parent est : c:\Test 21 Flot de lecture Etant donné la quantité d’information d’un fichier, il est peu conseillé voire impossible de le charger d'un bloc dans une variable. Un flot (ou flux) en lecture permet d’y accéder au fer et à mesure : donnée par donnée, "un peu comme un tuyau". Le flot doit être ouvert puis on accède aux données selon la nature du flot : Caractère par caractère. Par blocs de caractère. Avec la gestion d'un tampon. Séquentiellement ou directement à tel position. ..... Ces différents modes expliquent le nombre important de classes de flot en Java. Enfin on le ferme. 22 Lire un fichier caractère par caractère et l’afficher à l’écran import java.io.*; public class LireFichier1 { public static void main(String[] args) { La classe FileReader est un flot (flux) if (args.length!=1) { pour la lecture des caractères. System.out.println(" argument Permet d'accéder à un desseul fichiers sur SVPdisque. !"); System.exit(0); Instancie et ouvre en lecture un flot à } partir d'un objet File. Méthodes : Fichier fichier= new Fichier(args[0]); read : lit un caractère sur if (!fichier.lirePossible()) { le flot. close : ferme le flot. System.out.println(args[0] L'instruction de controle try...catch est obligatoire, +" "+fichier.proprietes()); car la méthode read peut lever (déclencher) une System.exit(0); exception (erreur grave). } try { FileReader flotLecture = new FileReader (fichier); long longueurFichier= fichier.length(); int dejaLu = 0; char car=0; Exécution: while (dejaLu < longueurFichier) { java LireFichier1 test3 car= (char)flotLecture.read(); Bonjour dejaLu = dejaLu + 1; System.out.print(car); Tous Le} flotLecture.close(); Monde } catch!!!(IOException e) { System.out.println(" erreur :" + e.toString()); } } } 23 Ecrire des caractères dans un fichier import java.io.*; public class EcrireFichier1 { La classe FileWriter est un flot (flux) pour public static void main(String[] args) l'écriture des caractères. { Permet d'accéder à des fichiers sur if (args.length!=1) { disque. System.out.println(" un seul argument Instancie SVP et ouvre !");en écriture un flot à partir d'un objet File. System.exit(0); Méthodes : } Fichier write (char) écritnew un caractère sur le flot. fichier= Fichier(args[0]); write (String) écrit le String. if close ferme le flot. (!fichier.ecrirePossible()) System.out.println(args[0] +" "+fichier.proprietes()); else { try { FileWriter flotEcriture = new FileWriter(fichier); Exécution: for (char car='a'; car<='z'; ++car) java EcrireFichier1 test flotEcriture.write (car); cat test flotEcriture.close (); abcdefghijklmnopqrstuvwxyz } catch (IOException e) { System.out.println(" erreur :" + e.toString()); } } } } 24 Classe PrintWriter La classe PrintWriter permet d'écrire sur un flot de sortie des données en les représentant à l'aide de chaînes de caractères, à l'aide des méthodes print et println. import java.io.*; class Ecrire2{ public static void main(String[] argv) throws IOException FileWriter fichier =new FileWriter ("test"); PrintWriter ecrivain= new PrintWriter (fichier); ecrivain.println ("bonjour, comment cela va-t-il ?"); ecrivain.println ("un peu difficile ?"); ecrivain.println ("On peut mettre des entiers : "+10); ecrivain.println ("Voici un caractère : "+'A'); ecrivain.close(); } { } 25 Classe PrintWriter import java.io.*; Exécution: class Ecrire2{ java Ecrire2 public static void main(String[] argv) throws IOException { cat FileWriter test FileWriter fichier =new ("test"); ("test",true); comment(fichier); cela va-t-il ? PrintWriter ecrivain=bonjour, new PrintWriter un peu difficilecela ? va-t-il ?"); ecrivain.println ("bonjour, comment Ondifficile peut mettre ecrivain.println ("un peu ?"); des entiers : 10 Voicimettre un caractère : A : "+10); ecrivain.println ("On peut des entiers ecrivain.println ("Voici un caractère : "+'A'); ecrivain.close(); }} Exécution: java Ecrire2 cat test bonjour, comment cela va-t-il ? un peu difficile ? On peut mettre des entiers : 10 Voici un caractère : A 26 Classe PrintWriter Exécution: import java.io.*; class Ecrire2{ javac Ecrire2.java public static void main(String[] argv) throws IOException { java Ecrire2 FileWriter fichier =new FileWriter ("test",true); java Ecrire2 PrintWriter ecrivain= new PrintWriter (fichier); cat testcomment cela va-t-il ?"); ecrivain.println ("bonjour, ecrivain.println ("un bonjour, peu difficile ?"); cela va-t-il ? comment ecrivain.println ("Onun peut des? entiers : "+10); peumettre difficile ecrivain.println ("Voici caractère "+'A'); Onun peut mettre :des entiers : 10 ecrivain.close(); }} Voici un caractère : A bonjour, comment cela va-t-il ? un peu difficile ? On peut mettre des entiers : 10 Voici un caractère : A 27 Rechercher un mot dans un fichier import java.io.*; import java.util.Scanner; class find{ public static void rechercher (String mot, File fichier){ String line = null; try { BufferedReader br = new BufferedReader(new FileReader(fichier)); int i = 1; //initialisation du numero de ligne while ((line = br.readLine()) != null) { if ( line.indexOf(mot) != -1) System.out.println("Mot trouve a la ligne " + i ); i++; } br.close(); } catch(IOException ioe) { System.out.println("Erreur IO" ); } } public static void main(String args[]) { System.out.println ("Veuillez saisir un mot :"); Scanner sc = new Scanner (System.in); String str = sc.nextLine(); rechercher (str, new File(args[0])); } } Exécution : $ java find find.java Veuillez saisir un mot : java Mot trouve a la ligne 1 Mot trouve a la ligne 2 28 Sérialisation 29 Sérialisation : enregistrer et restaurer des objets La sérialisation est un procédé introduit dans le JDK version 1.1 qui permet de rendre un objet persistant. Un objet est persistant si sa durée de vie est supérieure au programme qui l’a crée. Cet objet est mis sous une forme sous laquelle il pourra être reconstitué à l’identique. Ainsi il pourra être stocké sur un disque dur ou transmis au travers d’un réseau pour le créer dans une autre JVM. C’est le procédé qui est utilisé par exemple, par les sockets pour transmettre un objet via le réseau. Un objet sérialisable est transformable en une suite séquentiel d’octet et inversement, donc peut être stocké dans un fichier. 30 Objet Serializable import java.io.Serializable; class Compte implements Serializable { private String titulaire; private int numeroCompte; private double solde; Compte (String titulaire, int numeroCompte, double solde){ this.titulaire = titulaire; this.numeroCompte = numeroCompte; this.solde = solde; } public String toString (){ return "titulaire : "+ this.titulaire +"\t numeroCompte : "+this.numeroCompte +"\t solde : "+ this.solde; } } Serializable est une Interface sans méthode à implémenter. 31 Ecrire des objets dans un fichier import java.io.*; import java.util.*; public class EcrireBanque { public static void main(String[] args) { File fichier= new File("banque"); try { ObjectOutputStream flotEcriture =new ObjectOutputStream(new FileOutputStream(fichier)); ArrayList<Compte> liste=new ArrayList<Compte>(); liste.add(new Compte("aa",1,1000)); liste.add(new Compte("ab",2,2000)); liste.add(new Compte("ac",3,3000)); liste.add(new Compte("ad",4,4000)); flotEcriture.writeObject(liste); flotEcriture.close(); } catch (IOException e) {} } } 32 Exécution java EcrireBanque cat banque (pour visualiser le contenu) í ♣sr ‼java.util.ArrayListx?Ò↔TÇa?♥ ☺I ♦sizexp ♦w♦ r ♠Compte→¥!7Þt┼à☻ ♥I ♀numeroCompteD ♣soldeL titulairet ↕Ljava/lang/String;xp ☺@?@ t ☻aasq ~ ☻ ☻@Y@ t ☻absq ~ ☻ ♥@§p t ☻acsq ~ ☻ ♦@¯@ t ☻adx 33 Classe ObjectOuputStream Cette classe permet de sérialiser un objet. On définit un fichier avec la classe FileOutputStream. On instancie un objet de classe ObjectOutputStream en lui fournissant en paramètre le fichier : ainsi, le résultat de la sérialisation sera envoyé dans le fichier. On appelle la méthode writeObject() en lui passant en paramètre l’objet à sérialiser. On appelle la méthode close() pour terminer l’opération. Lors de ces opérations une exception de type IOException peut être levée si un problème intervient avec le fichier. Après l’exécution de cet exemple, un fichier de sauvegarde est créé. On peut visualiser son contenu mais surtout pas le modifier car sinon il serait corrompu. En effet, les données contenues dans ce fichier ne sont pas toutes au format caractères. 34 Lire des objets dans un fichier import java.io.*; import java.util.*; public class LireBanque { public static void main(String[] args) { File fichier= new File("banque"); try { ObjectInputStream flotLecture = new ObjectInputStream(new FileInputStream(fichier)); Object lu = flotLecture.readObject(); ArrayList liste=(ArrayList)lu; for (int i=0; i<liste.size(); i++) { Object elem = liste.get(i); System.out.println(elem); } flotLecture.close(); } catch (Exception e) {} } } 35 Classe ObjectInputStream Cette classe permet de désérialiser un objet. On créer un objet de la classe FileInputStream qui représente le fichier contenant l’objet sérialisé. On créer un objet de type ObjectInputStream en lui passant le fichier en paramètre. Un appel à la méthode readObject() retourne l’objet avec un type Object. Un cast est nécessaire pour obtenir le type de l’objet. La méthode close() permet de terminer l’opération. 36 Exécution Exécution: java EcrireBanque cat banque (pour visualiser le contenu) í ♣sr ‼java.util.ArrayListx?Ò↔TÇa?♥ ☺I ♦sizexp ♦w♦ r ♠Compte→¥!7Þt┼à☻ ♥I ♀numeroCompteD ♣soldeL titulairet ↕Ljava/lang/String;xp ☺@?@ t ☻aasq ~ ☻ ☻@Y@ t ☻absq ~ ☻ ♥@§p t ☻acsq ~ ☻ ♦@¯@ t ☻adx Exécution : java LireBanque titulaire : aa numeroCompte : 1 titulaire : ab numeroCompte : 2 titulaire : ac numeroCompte : 3 titulaire : ad numeroCompte : 4 solde : 1000.0 solde : 2000.0 solde : 3000.0 solde : 4000.0 37