Cours de JAVA Quelques classes remarquables de JAVA Emmanuel ADAM Institut des Sciences et Techniques de Valenciennes Université de Valenciennes et du Hainaut-Cambrésis source principale : « Thinking in Java (B. Eckel) » Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 1 Quelques classes remarquables de JAVA Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 2 La classe Object Il s’agit de la classe principale, elle contient les fonctions : protected Object clone() qui crée et retourne une copie de l’objet boolean equals(Object obj) qui détermine si obj est égal à l’objet courant. protected void finalize() appelé par le ramasse miettes s’il n’y a plus de référence à l’objet Class getClass() retourne la classe courante de l’objet int hashCode() retourne une clé pouvant être utilisée pour un tri void notify() réveille un processus en attente sur l’objet void notifyAll() réveille tous les processus en attente String toString() retourne une chaîne représentant l’objet void wait() met en pause le processus courant en attendant un réveil Tous les objets Java héritent donc de ces méthodes Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 3 La classe System Gestion du système : static PrintStream err : sortie d'erreur standard static InputStream in : entrée standard static PrintStream out : sortie standard static void arraycopy(...) : copie de tableaux static long currentTimeMillis() : temps courant en millisecondes static long nanoTime() : temps courant en nanoseconde static void exit(int status) : sortie de programme static void gc() : lance le ramasse-miettes static void load(String fichier) : charge le code en tant que librairie dynamique Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 4 La classe System Gestion des propriétés du système : static String getProperty(String key): retourne la valeur de la propriété spécifiée par la clé static Properties getProperties(): retourne les propriétés du système static String setProperty(String key, String value) : affecte une nouvelle valeur à une propriété static void setProperties(Properties props) : affecte des propriétés java.version : version de l'interpréteur Java. java.home : répertoire d'installation de Java. user.home : répertoire de l'utilisateur java.class.path : valeur du classpath file.separator, path.separator, line.separator... Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 5 La classe String (1) Les chaînes sont constantes, leurs valeurs ne peuvent être changées après leurs créations. StringBuffer permet l’utilisation de chaînes "dynamiques". Construction : String str = "abc"; est équivalent à char data[] = {'a', 'b', 'c'}; String str = new String(data); La classe String comporte des méthodes d’accès aux caractères, de comparaisons, de recherche, d’extraction, de copie, de conversion minuscules/majuscule, ... Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 6 La classe String (2) L’opérateur (+) est surchargé pour permettre la concaténation, et à la conversion implicite d’objets en chaîne. Toute conversion se fait de manière automatique en faisant appel à la méthode toString() héritée de la classe Object. Il est donc possible de surcharger cette méthode dans les nouvelles classes créées. Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 7 La classe String (3) String permet de tronçonner une chaîne (abandon de StringTokenizer) String ch = "une chaîne à tronçonner"; String[]mots1 = ch.split(" "); String[]mots2 = ch.split("n"); String[]mots3 = ch.split("n",3); ["une";"chaîne";"à";"tronçonner"] ["u";"e chaî";"e à tro";"ço";"";"er"] ["u";"e chaî";"e à tronçonner"] Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 8 La classe StringBuffer A utiliser si besoin de chaînes dynamiques (modifications, concaténation, …) int taille = 30000; long tpsDebut = System.currentTimeMillis(); String ch = new String(); for(int i=0; i<taille; i++) ch += i; System.out.println(ch); long tpsFin = System.currentTimeMillis(); System.out.println("tps = "+ (tpsFin – tpsDebut)); tpsDebut = System.currentTimeMillis(); StringBuffer sb = new StringBuffer(); String sep = ", "; for(int i=0; i<taille; i++) sb.append(i).append(sep); System.out.println(sb); tpsFin = System.currentTimeMillis(); Le gain de temps pour la création de la chaîne représentant un tableau de 30000 entiers est ici de 7 sec environ !!! par rapport au code précédent (test sur java 1.6, Pentium M 1.6 MHz) System.out.println("tps = "+ (tpsFin – tpsDebut)); Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 9 Des classes très utiles (import java.util.*) Interfaces : Collection, Comparator, Enumeration, EventListener, Iterator, List, ListIterator, Map, Map.Entry,Observer, Set, SortedMap, SortedSet Classes : AbstractCollection, AbstractList, AbstractMap, AbstractSequentialList, AbstractSet, ArrayList, Arrays, BitSet, Calendar, Collections, Date, Dictionary, EventObject, GregorianCalendar, HashMap, HashSet, Hashtable, LinkedList, ListResourceBundle, Locale, Observable, Properties, PropertyPermission, PropertyResourceBundle, Random, ResourceBundle, SimpleTimeZone, Stack, StringTokenizer, TimeZone, TreeMap, TreeSet, Vector, WeakHashMap Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 10 La classe Arrays Cette classe contient des méthodes statiques pour la gestion de tableaux : static int binarySearch(int []tab, int valeur) retourne l’index de la valeur, -1 si introuvable static boolean equals (boolean []tab1, boolean []tab2) static void fill (double []tab, double valeur) remplit le tableau avec la valeur static void fill (char []tab, int debut, int fin, char valeur) static void sort (long []tab) static void sort (short [] tab, int debut, int fin) s’appliquent à tous types de tableaux : d’entiers, de réels, d’objets (références seules prises en compte) Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 11 La classe Arrays int []tab = new int[100]; 56, 82, 84, 7, 87, 82, 23, 15, 37, 0, 32, 27, 11, 77, 59, 46, for(int i=0; i<tab.length; i++) 95, 54, 63, 80, 72, 78, 43, 88, 97, 65, 91, 82, 20, 69, 18, tab[i] = (int)(Math.random()*100); 44, 67, 91, 81, 22, 11, 36, 86, 96, 5, 36, 90, 66, 71, 50, 6, 59, 63, 48, 54, 6, 23, 46, 55, 41, 35, 69, 32, 50, 25, 64, 71, 82, 16, 13, 56, 65, 88, 1, 60, 76, 18, 52, 28, 27, 3, 45, 37, 87, 0, 31, 32,45, 25, 31, 59, 91, 28, 83, 78, 28, 4, 33, 40, 72, 48, 45, 44, 22, long tpsDebut = System.currentTimeMillis(); 0, 0, 1, 3, 4, 5, 6, 6, 7, 11, 11, 13, 15, 16, 18, 18, 20, 22, 22, 23, 23, 25, 25, java.util.Arrays.sort(tab); 33, 35, 36, 36, 37, 46, 48, 48, 50, 50, 63, 63, 64, 65, 65, long tpsFin = System.currentTimeMillis(); 78, 78, 80, 81, 82, 90, 91, 91, 91, 95, 27, 37, 52, 66, 82, 96, 27, 40, 54, 67, 82, 97, 28, 41, 54, 69, 82, 28, 43, 55, 69, 83, 28, 44, 56, 71, 84, 31, 44, 56, 71, 86, 31, 45, 59, 72, 87, 32, 45, 59, 72, 87, 32, 45, 59, 76, 88, 32, 46, 60, 77, 88, tri effectue en 0 millisecondes 1039728793720,1039728793720 System.out.println("tri effectue en " + (tpsFin - tpsDebut) + " millisecondes"); Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 12 Autre fonctions sur les tableaux static void arraycopy(Object tabSource, int debutSource, Object tabDest, int debutDest, int longeur) est une méthode statique et native de la classe System à utiliser pour copier les tableaux. int []tab2 = new int[100]; System.arraycopy(tab, 0, tab2, 0, 100); Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 13 Vector La classe Vector est la plus utilisée. Elle permet de stocker des objets dans un ensemble de longueur variable. add (objet) permet d’ajouter un objet en queue, get(index) permet de récupérer l’objet positionné à l’index donné, find() permet de récupérer la position de l’objet, isEmpty() teste si le vecteur est vide, size() donne la taille du vecteur, toArray() retourne un tableau d’objets contenus dans le vecteur La classe ArrayList est l’identique de la classe Vector, mais n’est pas synchronisée, elle est donc plus rapide et à utiliser de préférence Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 14 Quelques classes de java.util La classe Stack hérite directement de la classe Vector et ajoute entre autres les méthodes : push(objet) : ajoute un objet en tête ; pop() : retire le premier objet ; peek() : renvoie une référence au premier objet sans le retirer ; empty() : teste si la pile est vide. Une pile peut aussi contenir des objets de différents types. Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 15 Quelques classes de java.util La classe Hashtable peut être vue comme un dictionnaire composé de deux vecteurs : un vecteur pour la clé et un vecteur pour l’objet. Une table de clés possède les méthodes : put(clé, objet) : get(clé) : containsKey(clé) : containsValue(objet) : : entre autres... isEmpty() Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 16 Quelques classes de java.util La classe Set définit un ensemble ne pouvant contenir qu’un exemplaire d’un objet. Cette classe dispose, entre autres, des méthodes : add(objet) qui n’ajoute l’objet que s’il n’est pas déjà présent contains(objet) ; remove(objet) ; isEmpty(). Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 17 Quelques classes de java.util L’interface Enumeration ne contient que deux méthodes : : retourne l’objet (à caster) courant et passe à l’élément suivant, hasMoreElements() : indique la présence d’au moins un élément. nextElement() Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 18 Quelques classes de java.util ● ● L’interface Enumeration (suite) utilisée surtout pour la lecture des éléments d’un vecteur : for(Enumeration e=vecteur.elements();e.hasMoreElements();) System.out.println((Personne)e.nextElement()) ; (mais elle est plus longue que get(index)) int taille = vecteur.size(); for(int i = 0; i<taille;i++) System.out.println((Personne)vecteur.get(i)) ; Remarque : elements() est la méthode qui retourne une énumération à partir du vecteur. Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 19 Trier les éléments d’une ArrayList (1/3) de la classe Collections permet de trier une liste d’objets implémentant l’interface Comparable. public static void sort (List list) si la classe des objets à trier n’implémente pas l’interface Comparable, il faut alors fournir un Comparator. Exemple de tri d’Integer dans une ArrayList : java.util.ArrayList al = new java.util.ArrayList(); for(int i=0; i<1000; i++) al.add(new Integer((int)(Math.random()*1000))); java.util.Collections.sort(al); // car une ArrayList implémente une List Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 20 Trier les éléments d’une ArrayList (2/3) /**Définition d’une classe implémentant l’interface Comparable */ class Personne implements Comparable { String nom; private int noSecu; Personne(){nom = ""; noSecu = 0;} Personne(String _nom, int _noSecu) {nom = _nom; noSecu = _noSecu;} public String toString() { return nom+":"+noSecu; } } /**retourne –1 si objet < autre, 0 si objet == autre, 1 si objet > autre*/ public int compareTo(Object autre) { Personne p = (Personne)autre; return (nom.compareToIgnoreCase(p.nom)); } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 21 Trier les éléments d’une ArrayList (3/3) java.util.ArrayList al = new java.util.ArrayList(); for(int i=0; i<10; i++) al.add(new Personne("nom"+(int)(Math.random()*10), i)); String ch = ""; for(int i=0; i<al.size(); i++) ch = ch + (Personne)al.get(i) + ", "; System.out.println(ch); java.util.Collections.sort(al); ch = ""; for(int i=0; i<al.size(); i++) ch = ch + (Personne)al.get(i) + ", "; System.out.println(ch); nom6:0, nom8:1, nom2:2, nom4:3, nom0:4, nom8:5, nom2:6, nom2:7, nom8:8, nom9:9, nom0:4, nom2:2, nom2:6, nom2:7, nom4:3, nom6:0, nom8:1, nom8:5, nom8:8, nom9:9, Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 22 Listes Génériques (depuis 1.5) ● ● Nécessité de préciser le type d'objets dans la collection But : Sécuriser le code import java.util.ArrayList; ArrayList <Personne>liste = new ArrayList<Personne>(); for(int i=0; i<10; i++) liste.add(new Personne("nom"+i, i)); String ch = ""; for(Personne p : liste) ch = ch + p + ", "; System.out.println(ch); Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 23 Méthodes Génériques (depuis 1.5) ● ● ● Utilisation de caractères spéciaux (wilcard) remplaçant un type inconnu void listeObjet(ArrayList<?> liste) { for (Object o : liste) System.out.println(o); } void <T>tabVersliste(T[]tab, ArrayList<T> liste) { for (T obj : tab) liste.add(obj); } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 24 Méthodes Génériques (depuis 1.5) ● ● ● wilcard remplaçant une sorte d'objet void listeObjet(ArrayList<? extends Animal> liste) { for (Animal a : liste) a.affiche(); } <T, E extends T> E getObjet(ArrayList<T> liste) Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 25 Classe Génériques (depuis 1.5) Définition d'une classe utilisant des listes génériques : class MaClasseGen<P extends Personne,A extends Animal> { ArrayList<A> listeA; ArrayList<P> listeP; MaClasseGen(){ listeP = new ArrayList<P>(); listeA = new ArrayList<A>(); } void add(P p) {listeP.add(p);} void add(A a) {listeA.add(a);} } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 26 Classe Génériques (depuis 1.5) Utilisation d'une classe utilisant des listes génériques : MaClasseGen<PersonneF, AnimalA> mcg = new MaClasseGen<PersonneF, AnimalA>(); mcg.add(new PersonneF("aa","a")); mcg.add(new AnimalA("aa")); mcg.add(new AnimalA("cc")); Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 27 Gestion d’exceptions Quelques classes remarquables de JAVA Emmanuel ADAM Institut des Sciences et Techniques de Valenciennes Université de Valenciennes et du Hainaut-Cambrésis source principale : « Thinking in Java (B. Eckel) » Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 28 Les exceptions La gestion des exceptions est très importante, voire primordiale, dans tous systèmes informatiques. Elle confère un aspect beaucoup plus professionnel aux applications. Eviter les applications qui plantent sans information précise, ex : Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 29 Les exceptions (2) Les exceptions sont des instances des classes héritant des classes java.lang.Error (pour des erreurs graves quasi impossibles à gérer : plus de mémoire, classe manquante, ...) java.lang.Exception (pour des exceptions attendues sinon probables pouvant être gérée : débordement d’un tableau, erreur de calcul, ...). Ces deux classes implémentent l’interface Throwable Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 30 Les exceptions (3) La classe Exception possède deux constructeurs Exception() et Exception (String msg) ). Elle hérite de l’interface Throwable de : getMessage qui permet de récupérer le message de l’exception s’il existe. toString, qui retourne la classe et le message sous forme de chaîne. printStackTrace, qui fait appel à toString, mais qui en plus indique l’endroit du programme où a été levée l’exception. Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 31 Capture d’une exception Pour récupérer, ou attraper, une exception : …. try {…. //endroit où pourrait apparaître une exception } catch (type_exception_1 e1) { …. // traitement de l’exception de type 1 } catch (type_exception_2 e2) { …. // traitement de l’exception de type 2 } finally { …. // dans tous les cas, passer par ici } …. Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 32 Exemple (1) int[] a = {1,2,3,4,5,6,7,8,9,10}; Exception levée int[] b = {10,9,8,7,6,5,0,3,2,1}; int []c = new int[10]; for(int i=0; i<=10; i++) { try { c[i] = a[i] / b[i]; System.out.println("c["+i+"] = " + c[i]); } Exception attrapée et gérée catch(Exception e) { System.out.println("division par 0 ..."); c[i] = 0; System.out.println("dans ce cas c["+i+"] = " + c[i]); Reprise du } programme } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 33 Des classes d’Exception ClassNotFoundException, CloneNotSupportedException, IllegalAccessException, .InstantiationException, InterruptedException, NoSuchFieldException, NoSuchMethodException, RuntimeException, ArithmeticException, ArrayStoreException, ClassCastException, IllegalArgumentException, IllegalThreadStateException, NumberFormatException, IllegalMonitorStateException, IllegalStateException, IndexOutOfBoundsException, ArrayIndexOutOfBoundsException, StringIndexOutOfBoundsException, NegativeArraySizeException, NullPointerException, SecurityException, UnsupportedOperationException Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 34 Exemple (2) int[] a = {1,2,3,4,5,6,7,8,9,10}; int[] b = {10,9,8,7,6,5,0,3,2,1}; Exception levée int []c = new int[10]; for(int i=0; i<=10; i++) { try { c[i] = a[i] / b[i]; System.out.println("c["+i+"] = " + c[i]); } Erreur de calcul attrapée et gérée catch(ArithmeticException e) { System.out.println("division par 0 ..."); c[i] = 0; System.out.println("dans ce cas c["+i+"] = " + c[i]); } Autres erreurs catch(Exception e) { System.out.println("... erreur imprevue ...\n" + e); } } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 35 Propagation d’une exception Si une exception n’est pas gérée dans une procédure, elle se propage hors de la procédure, Il faut donc que cette procédure soit capable de propager l’exception (utilisation du mot clé throws), Si à la fin du programme, une exception n ’a pas été attrapée, la pile des méthodes traversées par l'exception est affichée. Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 36 Exemple (3) public void diviser() throws Exception{ for(int i=0; i<=10; i++) { c[i] = a[i] / b[i]; System.out.println("c[" + i + "] = " + c[i]); } } Exception propagée Exception levée void test() { try { diviser(); } catch(ArithmeticException e) { Exception attrapée et System.out.println("division par 0 ..."); gérée } catch(Exception e) { System.out.println("... erreur imprevue ...\n" + e); } System.out.println("suite du prog"); } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 37 Définir son exception Il est possible de définir une exception en la faisant dériver de la classe Exception : class MonExceptionDivision extends Exception { public String toString() { return "Problème de division"; } } Le mot clé throw permet de lancer son exception. Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 38 Exemple (4) Exception propagée public void diviser() throws Exception{ for(int i=0; i<=10; i++) { if (b[i] == 0) throw new MonExceptionDivision(); Exception lancée c[i] = a[i] / b[i]; System.out.println("c[" + i + "] = " + c[i]); } } void test() { try { diviser(); } Exception attrapée et catch(Exception e) { gérée System.out.println("... erreur : " + e); } System.out.println("suite du prog"); } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 39 Les Entrées-Sorties les package java.io.*/ java.nio.* Emmanuel ADAM Institut des Sciences et Techniques de Valenciennes Université de Valenciennes et du Hainaut-Cambrésis source principale : « Thinking in Java (B. Eckel) » http://www.laltruiste.com/coursjava/sommaire.html api java Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 40 La classe Java.lang.System Utilisation des classes et interfaces du package java.io Il existe trois flux (flots) : System.in : flux d’entrée standard, System.out : flux de sortie standard, System.err : flux de sortie pour message d’erreur. Les entrées sorties peuvent générer une exception de type IOException à gérer Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 41 Exemple de flux d’entrée standard import java.io.*; class Lire { Lecture d’un caractère au public static void main(String[] argv) clavier { int b, nb = 0; try { while((b = System.in.read()) != 13) // 13 = code retour chariot { nb++; System.out.println(b); // affiche les codes ascii des caractères } } catch(IOException e) { System.out.println(e); } } } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 42 Gestion de fichiers La classe File permet d’accéder aux caractéristiques des fichiers et répertoires. Trois constructeurs : File(File dir, String name) ; File(String path, String name); File(String path). Les différentes méthodes sont : canRead() ; canWrite() ; delete() ; equals(Object obj) ; exists() ; getAbsolutePath() ; getCanonicalPath() ; getName() ; getParent() ; getPath() ; hashCode() ; isAbsolute() ; isDirectory() ; isFile() ; lastModified() ; length() ; list(FilenameFilter filter) ; list() ; mkdir() ; mkdirs() ; renameTo(File dest) ; toString(). Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 43 Exemple d’utilisation de ‘File’ import java.io.*; public class ChercheFichier { public static void main(String args[]) { String nomFichier = "ChercheFichier.java" ; File f = new File(nomFichier); if (f.exists()) { String nomRep = f.getAbsolutePath(); // retourne le répertoire et le fichier nomRep = nomRep.substring(0, nomRep.lastIndexOf("\\")); System.out.println( nomFichier + " est dans le repertoire " + nomRep); System.out.println(" droits en lecture, ecriture : " + f.canRead() + "," + f.canWrite() ); } } } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 44 Flux d’entrées InputStream dont dérivent les classes ByteArrayInputStream, FileInputStream, FilterInputStream, ObjectInputStream, PipedInputStream, SequenceInputStream et StringBufferInputStream Reader (orientée caractères) dont dérivent les classes BufferedReader, LineNumberReader, CharArrayReader, FilterReader, PushbackReader, InputStreamReader, FileReader, PipedReader, StringReader Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 45 Flux de sorties OutputStream dont dérivent les classes ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, PipedOutputStream Writer (orientée caractères) dont dérivent les classes BufferedWriter, CharArrayWriter, FilterWriter, OutputStreamWriter, PipedWriter, PrintWriter, StringWriter Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 46 Ecriture directe dans un fichier ‘FileOutputStream’ Exemple d’écriture dans un fichier : public static void main(String args[]) { File f = new File("C:\\donnees", "data.txt"); try { FileOutputStream fos = new FileOutputStream(f); String s = new String (" Coucou "); Transformation d’une chaîne en int longueur = s.length(); tableau de bytes byte[] buffer = s.getBytes(); for(int i = 0; i < longueur; i++) fos.write(buffer[i]); fos.close(); } catch (Exception e) {} Ecriture d’un tableau de bytes } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 47 Lecture directe d’un fichier : ‘FileInputStream’ public static void main(String args[]) { File fichier = new File("C:\\donnees", "data.txt"); if (fichier.exists()) { String chaine = ""; Lecture d’un tableau de bytes FileInputStream fis = null; byte[] b = new byte[1024]; try { fis = new FileInputStream(fichier);} catch (FileNotFoundException fnfe) {System.out.println(fnfe);} try { int i =fis.read(b); } catch (IOException ioe) {System.out.println(ioe);} System.out.println(new String(b)); try { fis.close(); } catch (IOException ioclose) {System.out.println(ioclose);} } Transformation en chaîne } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 48 Ecriture filtrée dans un fichier ‘DataOutputStream’ Ecriture de données typées, (chaînes de caractères à éviter depuis jdk1.1) public static void main(String args[]) { File fichier = new File("data.bin"); try { FileOutputStream fos = new FileOutputStream(fichier); DataOutputStream dos = new DataOutputStream(fos); dos.writeBoolean(true); dos.writeInt(17); dos.writeDouble(17.89); dos.writeBoolean(false); dos.writeInt(16); dos.writeDouble(16.84); dos.close(); fos.close(); } catch (Exception e) {} } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 49 Lecture filtrée d’un fichier ‘DataInputStream’ Lecture de données typées, (sauf des chaînes de caractères depuis java 1.1) … File fichier = new File("data.bin"); if(fichier.exists()) { try { FileInputStream fis = new FileInputStream(fichier); DataInputStream dis = new DataInputStream(fis); System.out.println(dis.readBoolean() + "," + dis.readInt() + "," + dis.readDouble()); System.out.println(dis.readBoolean() + "," + dis.readInt() + "," + dis.readDouble()); dis.close(); fis.close(); } catch (Exception e) {} } … Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 50 Lecture en séquence de fichiers ‘SequenceInputStream’ SequenceInputStream(Enumeration e) : permet de lire les InputStream de l’énumération en séquence SequenceInputStream(InputStream s1, InputStream s2) : permet de lire deux InputStream en séquence public static void main(String args[]) { File fichier1 = new File("data1.txt"); File fichier2 = new File("data2.txt"); if(fichier1.exists() && fichier2.exists()) { try { FileInputStream fis1 = new FileInputStream(fichier1); FileInputStream fis2 = new FileInputStream(fichier2); SequenceInputStream sis = new SequenceInputStream(fis1, fis2); String chaine = ""; int caractere = 0; while ((caractere = sis.read()) !=-1) chaine += (char)caractere; System.out.println(chaine); sis.close(); fis1.close(); fis2.close(); } Affiche le contenu des catch (Exception e) {} deux fichiers à l’écran } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 51 Flots de caractères Notion de flot de caractères (characters Streams) : On ne travaille plus uniquement sur des bytes, mais sur des caractères Apparition de 2 classes : Writer et Reader FileReader <-> FileWriter <-> FileInputStream FileOutputStream Echange facile de données avec accents (unicode) Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 52 Entrée de flots de caractères Flot de caractères Description Reader Classe Abstraite pour flot d’entrée (InputStream) BufferedReader Bufférise les entrées ligne par ligne LineNumberReader Garde trace du nb de lignes lues CharArrayReader Lit un tableau de caractères InputStreamReader Transforme un flot de byte et car. Unicode FileReader Transforme des bytes lus depuis un fichier en car. FilterReader Classe abstraite pour filtrer les caractères d’entrées PipedReader Lecture depuis PipeWriter StringReader Lit depuis une chaîne de caractères Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 53 Sortie de flots de caractères Flot de caractères Description Writer Classe Abstraite pour flot de sortie (OutputStream) BufferedWriter CharArrayWriter InputStreamWriter Bufférise les sorties ligne par ligne Ecrit un tableau de caractères Transforme un flot de car. Unicode en flot de bytes FileWriter Transforme un fichier de car. en flot de bytes PrintWriter Ecrit des valeurs et des objs dans un Writer PipedWriter Ecrit dans un PipeWriter StringWriter Ecrit dans une chaîne de caractères Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 54 Exemple (FileWriter) public static void main(String args[]) { File f = new File("C:\\Progjava\\fichier", "Essai.txt"); try { FileWriter fw = new FileWriter(f); PrintWriter pw = new PrintWriter(fw); // ou PrintWriter pw = new PrintWriter(new FileWriter(f)); pw.println("coucou"); pw.close(); fw.close(); } catch (Exception e) {} } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 55 Exemple (FileReader) public static void main(String args[]) { String chaine = ""; File f = new File("C:\\Progjava\\fichier", "Essai.txt"); try { } FileReader fr = new FileReader(f); BufferedReader br = new BufferedReader(fr); // ou BufferedReader br = new BufferedReader(new FileReader(f)); chaine = br.readLine(); // retourne null si fin de fichier br.close(); fr.close(); } catch (Exception e) {} System.out.println(chaine); Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 56 Exemple (Saisie clavier) public static void main(String args[]) { String chaine = ""; try { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); chaine = br.readLine(); br.close(); isr.close(); } catch (Exception e) {} System.out.println(chaine); } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 57 Accès en lecture/écriture RandomAccessFile(String name, String mode) : ouvre le fichier selon le mode donné : r lecture seule; rw lecture/écriture; public static void main(String args[]) { File fichier = new File("ChercheFichier.java"); if(fichier.exists()) { try { RandomAccessFile raf = new RandomAccessFile(fichier, "rw"); long longueur = raf.length(); raf.seek(longueur); Se déplacer dans le fichier raf.writeBytes("// fin du fichier\n"); raf.close(); } catch (Exception e) {} Ajout d’une chaîne } (en fin de fichier ici) } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 58 La sérialisation Signifie persistance, Pour éviter la perte des données à la fin de l’exécution Si un objet contient un autre objet, ce dernier est aussi sérialisé, et on obtient un arbre de sérialisation Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 59 Sérialisation (2) Les objets transients (transitoires,éphémères) Ce sont des objets qui ne peuvent pas être sérialisés (processus, flux de données) Si ils sont définis en tant qu’attributs dans un objet sérialisé, il faut indiquer qu’ils sont transitoires idem si on ne veut pas que certains attributs d’un objet soient sérialisés Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 60 Syntaxe pour la sérialisation La classe doit implémenter l’interface serializable (pas de méthode à implémenter) Exemple : import java.io.*; class MaClasse implements Serializable { public transient Thread mathread; private String nom; private int total; ... Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 61 Sauvegarde d’un objet public static void main(String args[]) { Personne p1 = new Personne("p1", 25); Personne p2 = new Personne("p2", 50); File f = new File("C:\\Progjava\\fichier", "Essai.obj"); try { FileOutputStream fos = new FileOutputStream(f); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(p1); oos.writeObject(p2); oos.close(); fos.close(); } catch (Exception e) {} } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 62 Lecture d’un objet persistant public static void main(String args[]) { File f = new File("C:\\Progjava\\fichier", "Essai.obj"); try { FileInputStream fis = new FileInputStream(f); ObjectInputStream ois = new ObjectInputStream(fis); Personne p1 = (Personne) ois.readObject(); Personne p2 = (Personne) ois.readObject(); ois.close(); fis.close(); } catch (Exception e) {} } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 63 Les canaux les package java.nio.channels.* Les canaux peuvent être bidirectionnel ; apporte la sécurité par la notion de verrou ; gestion de flux en mémoire La classe Channels permet la conversion des flux d'entrée/sortie en canaux de lecture/écriture, des canaux de lecture/écriture en flux d'entrée/sortie, Les canaux FileChannel sont spécialisés dans la gestion des fichiers : Lecture, écriture, positionnement, troncature et blocage par verrou Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 64 Les canaux les package java.nio.channels.* Un objet Pipe est constitué d'un canal en lecture et d'un canal en écriture, utilisables Les canaux ServerSocketChannel et SocketChannel définissent les canaux par sockets (serveur et client) Récupération d'un canal à partir d'un flux par getChannel() FileInputStream fis = new FileInputStream(new File("chemin")); FileChannel fc = fis.getChannel(); Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 65 Les canaux les package java.nio.channels.* Ouverture d'un canal à sa création (isOpen()) en lecture, écriture, lecture.écriture Plusieurs méthodes de lectures/écritures par les interfaces ReadableByteChannel et WritableByteChannel Possibilité de : fermer un canal lecture/écriture à une position donnée, forçage de l'écriture sur le support physique, protection par verrou d'une zone du canal Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 66 Les tampons les package java.nio.* Utilisation de tampon ByteBuffer , IntBuffer, ... pour des données binaires Tampon = séquence finie, linéaire, de primitives Principales propriétés = capacité, limite, position, marque Capacité = nb d'éléments, fixe Limite = index du premier élément non modifiable/lisible Position = index du prochain élément modifiable/lisible Marque = index de retour Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 67 Les tampons les package java.nio.* clear() : limite <-- 0 et position <-- 0 flip() : limite <-- position puis position <-- 0 rewind() : position <-- 0 reset() : position <-- marque Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 68 Copie de fichier par canaux les package java.nio.* void copieFichier(File ficSource, File ficDestination, boolean rapide){ try { FileInputStream fisSource = new FileInputStream(ficSource); FileOutputStream fosDestination = new FileOutputStream(ficDestination); FileChannel canalSource = fisSource.getChannel(); FileChannel canalDestination = fosDestination.getChannel(); ByteBuffer tampon = null; if(rapide) tampon = ByteBuffer.allocateDirect(1024); else tampon = ByteBuffer.allocate(1024); int nb_octets = 0; while ((nb_octets = canalSource.read(tampon)) > -1) { tampon.flip(); canalDestination.write(tampon); tampon.clear(); } } } catch(IOException e) { e.printStackTrace(); } Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 69 Les tampons les package java.nio.* Tampon peut être direct, alors : la JVM tente d'utiliser des opérations natives sur le buffer Évite de copier en dur à chaque opération Coût allocation élevé à réserver pour large tampon utilisé sur une longue durée Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 70 Les tampons les package java.nio.* Transfert du fichier en mémoire : MappedByteBuffer File fichier = new File("c:\\source.txt"); RandomAccessFile raf= new RandomAccessFile(fichier, "rw"); FileChannel canal= raf.getChannel(); MappedByteBuffer tampon= canal.map(FileChannel.MapMode.READ_WRITE, 0, fc.size()); Impossibilité pour un processus d'accéder à un fichier mappé => penser à clore le canal load() charge le tampon en mémoire isLoad() vérifie son chargement force() provoque l'écriture sur le fichier réel Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 71 Vérouillage de canaux les package java.nio.* Possibilité de mise en place d'un verrouillage d'une partie ou de la totalité d'un fichier. (classe FileLock) Objectif : coordonner l'accès à un fichier Un verrou peut être : Exclusif : seul le code le posant peut agir sur le canal Partagé : aucun autre code ne peut poser de verrous exclusifs boolean acces_partage = false; FileLock verrou = canal.lock(debut, taille, acces_partage); //ou FileLock verrou = canal.lock(); Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 72 Vérouillage de canaux les package java.nio.* Un verrou sur un canal bloque un autre programme appelant => demande d'obtention du verrou : FileLock monVerrou = canal.tryLock(); Possibilité de verrou sur une partie Libération d'un verrou : verrou.release(); Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 73 Canaux de socket les package java.nio.* Deux classes : ServerSocketChannel et SocketChannel Un ServerSocketChannel attend des connections et crée des SocketChannel. Un socketchannel est associé à une socket getChannel() Un socketchannel peut être bloquant ou non. ConfigureBlocking(true) ; isBlocking(). Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 74 Canaux de socket les package java.nio.* ServerSocketChannel Créé par ServerSocketChannel.open() Lié à un ServerSocket récupérable par socket() Relier le socket serveur à un port : bind(new InetSocketAddress(noPort)) Le ServerSocketChannel est alors lié à ce port Peut accepter plusieurs connections Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 75 Canaux de socket les package java.nio.* SocketChannel Créé par SocketChannel.open() Connection au serveur par connect(SocketAddress a) non bloquant, connect() accepté de suite bloquant, la connection tourne en fond Vérification de la demande de connection : isConnectionPending() Vérification du résultat de la connection : isConnected() Demande la fin de la connection : finishConnect() Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 76 Encodage/décodage les package java.nio.charset.* Le décodage : processus de transformation d'un bloc d'octets (bytes) en une chaine de caractères, selon un jeu de caractères (charset). L'encodage : processus de tranformation d'une séquence de caractères en un bloc de données selon un jeu de caractères. Liste de jeux de caractères disponibles (ISO-8859-1, UTF-8, ...): Charset.availableCharsets() Récupérer un CharSet : Charset.forName("ISO-8859-1"); Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 77 Encodage/décodage les package java.nio.charset.* Obtenir un décodeur et encodeur d'un CharSet : CharsetDecoder decodeur = leCharSet.newDecoder(); CharsetEncoder encodeur = leCharSet.newEncoder(); Un décodeur décode un tampon d'octets en un tampon de caractères ByteBuffer tampon = ByteBuffer.allocate(1024); ... CharBuffer cb = decoder.decode(tampon); Un encodeur encode un tampon de caractères, ou une chaîne, d'octets en un tampon d'octets String chaine = "Une chaîne de caractères..."; CharBuffer cb = CharBuffer.wrap(chaine); ByteBuffer bb1 = encoder.encode(cb); ByteBuffer bb2 = encoder.encode("Une chaîne"); Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 78 Encodage/décodage les package java.nio.charset.* Gestion des erreurs (encodage et décodage) : D'entrée : onMalformedInput De caractère : onUnmappableCharacter Possibilité de : Ignorer l'erreur (IGNORE) Remplacer l'entrée par une valeur de remplacement (REPLACE) Reporter (REPORT)l'erreur par la levée d'exception ou par un objet CoderResult ByteBuffer bb = leCharSet.newDecoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE) .decode(bb); Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 79 Encodage/décodage les package java.nio.charset.* Récupérer les erreurs : CodingErrorAction actionEntreeIncorrecte = leCharSet.malformedInputAction(); CodingErrorAction actionCaractereInconnu = leCharSet.unmappableCharacterAction(); Par la déclaration d'un CoderResult : Supposons un mauvais décodage : CharBuffer sortie = decodeur.decode(entree); déclenche une exception CoderResult erreur = decodeur.decode(entree, sortie, false); Retourne l'objet erreur isError(), isMalformed(), isOverflow(), isUnderflow(), isUnmappable() Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 80 Sélecteur de canaux les package java.nio.* Selector : utilisés pour des opérations d'entrée/sortie asynchrones,applications client/serveur. multiplexeur d'objets SelectableChannel. SelectionKey est un jeton de SelectableChannel auprès de Selector Création d'un sélecteur : Selector monSelecteur = Selector.open(); Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 81 Sélecteur de canaux les package java.nio.* Client A SocketChannel Client B SocketChannel Client C SocketChannel S E L E C T E U R clés Serveur Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 82 Sélecteur de canaux les package java.nio.* Le socket Serveur peut activer un sélecteur en cas : De connection d'un client (OP_ACCEPT) De connection (OP_WRITE) (OP_CONNECT),de lecture (OP_READ), d'écriture Enregistrement auprès d'un socket serveur par le sélecteur : ServerSocketChannel serveur = ServerSocketChannel.open(); ... SelectionKey cle = serveur.register(monSelecteur, SelectionKey.OP_ACCEPT); Le sélecteur enregistre les canaux provoquant l'opération associée int nbCles = monSelecteur.select(); Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 83 Sélecteur de canaux les package java.nio.* Récupération d'une clé : Set lesCles = selecteur.selectedKeys(); ... Iterator it = lesCles.iterator(); while(it.hasNext()){ SelectionKey uneCle = (SelectionKey)it.next(); //... } Récupérer un événement associé à une clé : uneCle.isAcceptable, isConnectable(), isReadable() et isWritable(). Lancer l'événement : SocketChannel canal = canal.accept(). Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 84 Sélecteur de canaux les package java.nio.* Redéfinir l'option du canal dans le sélecteur (pour lire les données): SelectionKey cleserveur = canal.register(selecteur, SelectionKey.OP_READ); La connexion est établie, les sockets (client et serveur) peuvent communiquer entre eux. Le canal référencé en lecture est sélectionné par le sélecteur. Pour désinscrire un canal et le supprimer du sélecteur : canal.keyFor(selecteur).cancel(); canal.close(); Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis –– Cours JAVA n°2 – p: 85