You are on page 1of 236

Timothy Fisher

LE GUIDE DE SURVIE

Java

LESSENTIEL DU CODE ET DES COMMANDES

Java

Timothy R. Fisher

CampusPress a apport le plus grand soin la ralisation de ce livre an de vous fournir une information complte et able. Cependant, CampusPress nassume de responsabilits, ni pour son utilisation, ni pour les contrefaons de brevets ou atteintes aux droits de tierces personnes qui pourraient rsulter de cette utilisation. Les exemples ou les programmes prsents dans cet ouvrage sont fournis pour illustrer les descriptions thoriques. Ils ne sont en aucun cas destins une utilisation commerciale ou professionnelle. CampusPress ne pourra en aucun cas tre tenu pour responsable des prjudices ou dommages de quelque nature que ce soit pouvant rsulter de lutilisation de ces exemples ou programmes.

Tous les noms de produits ou autres marques cits dans ce livre sont des marques dposes par leurs propritaires respectifs.
Publi par CampusPress 47 bis, rue des Vinaigriers 75010 PARIS Tl : 01 72 74 90 00 Ralisation PAO : La B Auteur : Timothy R. Fisher
ISBN : 978-2-7440-4004-7 Copyright 2009 CampusPress est une marque de Pearson Education France

Titre original : Java Phrasebook Traduit de lamricain par : Patrick Fabre ISBN original : 0-672-32907-7 Copyright 2007 by Sams Publishing www.samspublishing.com Tous droits rservs Sams Publishing 800 East 96th, Indianapolis, Indiana 46240 USA

Tous droits rservs

All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from Pearson Education, Inc. Aucune reprsentation ou reproduction, mme partielle, autre que celles prvues larticle L. 122-5 2 et 3 a) du code de la proprit intellectuelle ne peut tre faite sans lautorisation expresse de Pearson Education France ou, le cas chant, sans le respect des modalits prvues larticle L. 122-10 dudit code.

Table des matires

Introduction 1 Les bases Compiler un programme Java Excuter un programme Java Dfinir le chemin de classe 2 Interagir avec l'environnement Obtenir des variables d'environnement Dfinir et obtenir des proprits systme Parser des arguments en ligne de commande 3 Manipuler des chanes Comparer des chanes Rechercher et rcuprer des sous-chanes Traiter une chane caractre par caractre Renverser une chane par caractre Renverser une chane par mot Convertir une chane en majuscules ou en minuscules Supprimer les espaces au dbut et la fin d'une chane Parser une chane spare par des virgules

1 5 7 8 9 11 12 13 14 17 18 21 22 23 24 25 26 27

IV

Java

Travailler avec des structures de donnes Redimensionner un tableau Parcourir une collection en boucle Crer une collection mappe Stocker une collection Trouver un objet dans une collection Convertir une collection en un tableau

31 32 33 35 36 38 40 41 42 42 44 47 48 49 50 51 52 55 56 58 61 63 64

Dates et heures Retrouver la date d'aujourd'hui Conversion entre les objets Date et Calendar Imprimer une date/une heure dans un format spcifi Parser des chanes en dates Additions et soustractions avec des dates ou des calendriers Calculer la diffrence entre deux dates Comparer des dates Retrouver le jour de la semaine/ du mois/de l'anne ou le numro de la semaine Calculer une dure coule

Retrouver des motifs avec des expressions rgulires Les expressions rgulires en Java Retrouver une portion de texte l'aide d'une expression rgulire Remplacer du texte mis en correspondance Retrouver toutes les occurrences d'un motif Imprimer des lignes contenant un motif

Retrouver des caractres de nouvelle ligne dans du texte 65

Table des matires

Nombres Vrifier si une chane est un nombre valide Comparer des nombres virgule flottante Arrondir des nombres virgule flottante Formater des nombres Formater des devises Convertir un entier en nombre binaire, octal et hexadcimal Gnrer des nombres alatoires Calculer des fonctions trigonomtriques Calculer un logarithme

67 68 69 71 72 74 74 75 76 77 79 80 80 81 86 87 88 89 89 90 93 94 95 96 97

Entre et sortie Lire du texte partir d'une entre standard Ecrire vers une sortie standard Formater la sortie Ouvrir un fichier par son nom Lire un fichier dans un tableau d'octets Lire des donnes binaires Atteindre une position dans un fichier Lire une archive JAR ou ZIP Crer une archive ZIP

Travailler avec des rpertoires et des fichiers Crer un fichier Renommer un fichier ou un rpertoire Supprimer un fichier ou un rpertoire Modifier des attributs de fichier

VI

Java

Obtenir la taille d'un fichier Dterminer si un fichier ou un rpertoire existent Dplacer un fichier ou un rpertoire Obtenir un chemin de nom de fichier absolu partir d'un chemin relatif Dterminer si un chemin de nom de fichier correspond un fichier ou un rpertoire Lister un rpertoire Crer un nouveau rpertoire 10 Clients rseau Contacter un serveur Retrouver des adresses IP et des noms de domaine Grer les erreurs rseau Lire du texte Ecrire du texte Lire des donnes binaires Ecrire des donnes binaires Lire des donnes srialises Ecrire des donnes srialises Lire une page Web via HTTP 11 Serveurs rseau Crer un serveur et accepter une requte Retourner une rponse Retourner un objet Grer plusieurs clients Servir du contenu HTTP

98 99 99 101 102 103 106 107 108 109 110 111 112 113 114 115 117 118 121 122 123 124 126 128

Table des matires

VII

12 Envoyer et recevoir des e-mails Vue d'ensemble de l'API JavaMail Envoyer des e-mails Envoyer des e-mails MIME Lire un e-mail 13 Accs aux bases de donnes Se connecter une base de donnes via JDBC Envoyer une requte via JDBC Utiliser une instruction prpare Rcuprer les rsultats d'une requte Utiliser une procdure stocke 14 XML Parser du XML avec SAX Parser du XML avec DOM Utiliser une DTD pour vrifier un document XML Crer un document XML avec DOM Transformer du XML avec des XSLT 15 Utiliser des threads Lancer un thread Arrter un thread Attendre qu'un thread se termine Synchroniser des threads Suspendre un thread Lister tous les threads

131 132 133 135 137 141 142 144 146 148 149 153 155 157 159 161 163 165 166 168 169 171 174 176

VIII

Java

16 Programmation dynamique par rflexion Obtenir un objet Class Obtenir un nom de classe Dcouvrir des modificateurs de classe Trouver des superclasses Dterminer les interfaces implmentes par une classe Dcouvrir des champs de classe Dcouvrir des constructeurs de classe Dcouvrir des informations de mthode Retrouver des valeurs de champ Dfinir des valeurs de champ Invoquer des mthodes

179 180 182 182 183 185 186 187 189 191 192 193

Charger et instancier une classe de manire dynamique 195 17 Empaquetage et documentation des classes Crer un paquetage Documenter des classes avec JavaDoc Archiver des classes avec Jar Excuter un programme partir d'un fichier JAR Index 197 198 200 203 204 207

Au sujet de l'auteur
Timothy Fisher est un professionnel du dveloppement de logiciels Java depuis 1997. Il a revtu de nombreuses casquettes, dont celle de dveloppeur, de chef d'quipe et d'architecte en chef. Il est actuellement consultant pour l'entreprise Compuware Corporation Dtroit dans le Michigan. Il aime crire sur des sujets techniques et a contribu aux deux ouvrages Java Developer's Journal et XML Journal. Tim est galement passionn par l'ducation et l'utilisation des technologies Internet avances dans ce domaine. Pour le contacter et consulter son blog (en anglais), rendez-vous l'adresse www.timothyfisher.com.

Introduction
En dbut danne, un diteur de Pearson ma demand dcrire ce Guide de survie consacr au Java, opus dune collection regroupant un certain nombre dautres ouvrages, dont Christian Wenz avait crit le premier consacr au PHP (premire partie du Guide de survie PHP et MySQL). Lide de la collection Guide de survie est tire des guides de conversation pour le tourisme dans les pays trangers qui proposent des listes de phrases pour sexprimer dans une autre langue. Ces manuels sont trs utiles pour ceux qui ne connaissent pas la langue locale. Le principe des ouvrages de la collection Guide de survie est analogue. Ils montrent au lecteur comment raliser des tches courantes dans le cadre dune technologie particulire. Le but de ce Guide de survie est de fournir une liste dexemples de code couramment utiliss en programmation Java. Ce livre doit tre utile la fois au programmeur Java confirm et celui qui dbute avec ce langage. Sil peut tre lu de bout en bout afin dacqurir une vue densemble du langage Java, il est avant tout conu comme un ouvrage de rfrence qui peut tre consult la demande lorsque le programmeur doit savoir comment raliser une tche courante en Java. Vous pouvez aussi explorer ce livre afin de dcouvrir des fonctionnalits et des techniques Java que vous navez pas encore matrises.

Introduction

Ce livre nest pas un manuel dapprentissage ou dintroduction au Java ni une rfrence complte de ce langage. Il existe bien dautres classes et API que celles prsentes ici. Dexcellents livres ont dj t publis qui vous permettront dapprendre le Java ou serviront de rfrence en abordant toutes les fonctionnalits possibles et imaginables. Si votre but est dacqurir une comprhension trs vaste dune technologie spcifique, il est prfrable de consulter un livre adapt. La plupart des exemples prsents dans ce livre nincluent pas de code de gestion des erreurs. Bon nombre de ces fragments de code sont cependant susceptibles de lever des exceptions quil vous faudra imprativement grer dans vos propres applications. Le code de gestion des erreurs et des exceptions est volontairement omis ici, afin que le lecteur puisse se concentrer spcifiquement sur la notion illustre par lexemple, sans tre distrait par dautres considrations. Si les exemples avaient inclus lensemble du code de gestion des exceptions, ils nauraient pour la plupart pas pu prendre la forme compacte et synthtique qui est la leur et vous nauriez pas mieux compris les notions abordes. La JavaDoc du JDK Java est une excellente source dinformations pour retrouver les exceptions qui peuvent tre leves par les mthodes contenues dans les classes Java rencontres dans ce livre. Pour la consulter, rendez-vous ladresse http://java.sun.com/j2se/1.5.0/ docs/api/. Les exemples de ce livre doivent tre indpendants du systme dexploitation. Le mot dordre de la plate-forme Java ("programm une fois, excut partout") doit sappliquer tous les exemples contenus dans ce livre. Le code a t test sous le JDK 1.5 aussi appel Java 5.0.

La plupart des exemples fonctionnent aussi sous les versions prcdentes du JDK, sauf mention spciale ce sujet. Tous les exemples ont t tests et doivent tre exempts derreurs. Je souhaite pour ma part que le livre ne contienne pas la moindre erreur, mais il faut videmment admettre quaucun livre technique ne peut par dfinition y prtendre. Toutes les erreurs qui pourraient tre trouves dans louvrage seront signales sur le site www.samspublishing.com. En rdigeant ce livre, jai tent de trouver les exemples les plus utiles tout en mastreignant lexigence de concision de la collection Guide de survie. Il est immanquable qu un moment ou un autre, vous rechercherez un exemple qui ne figurera pas dans ce livre. Si vous estimez quun exemple important manque, signalez-le moi. Si vous pensez linverse que dautres exemples du livre ne sont pas si utiles, indiquez-le moi galement. En tant quauteur, japprcie toujours de connatre le sentiment des lecteurs. A lavenir, il est possible quune seconde dition du livre voit le jour. Vous pouvez me contacter en consultant mon site Web ladresse www.timothyfisher.com.

1
Les bases
Ce chapitre prsente les premiers exemples avec lesquels vous aurez besoin de vous familiariser pour dmarrer un dveloppement Java. Ils sont en fait requis pour raliser quelque action que ce soit en Java. Vous devez pouvoir compiler et excuter votre code Java et comprendre les chemins de classe Java. A la diffrence dautres langages comme le PHP ou le Basic, le code source Java doit tre compil sous une forme appele "code-octet" (bytecode) avant de pouvoir tre excut. Le compilateur place le code-octet dans des fichiers de classe Java. Tout programmeur Java doit donc comprendre comment compiler son code source en fichiers de classe et savoir excuter ces fichiers de classe. La comprhension des chemins de classe Java est importante la fois pour compiler et pour excuter le code Java. Nous commencerons donc par ces premiers exemples. Il est aujourdhui courant de travailler au dveloppement Java dans un EDI (environnement de dveloppement intgr) comme le projet libre Eclipse (http://www.eclipse .org). Pour ce chapitre, nous considrerons que vous raliserez vos tches en ligne de commande.

CHAPITRE 1 Les bases

Si lessentiel de votre dveloppement peut parfaitement se faire avec un EDI, tout dveloppeur se doit cependant dtre familiaris avec la configuration et la ralisation de ces tches en dehors dun EDI. La procdure propre aux tches effectues dans un EDI varie selon lEDI : il est donc prfrable dans ce cas de consulter le manuel de lEDI concern pour obtenir de laide ce sujet. Pour excuter les instructions contenues dans ce chapitre, vous devez obtenir une distribution Java auprs de Sun. Sun diffuse la technologie Java sous plusieurs formes. Les distributions Java les plus courantes sont le Java Standard Edition (SE), le Java Enterprise Edition (EE) et le Java Micro Edition (ME). Pour suivre tous les exemples de ce livre, vous naurez besoin que du paquetage Java SE. Java EE contient des fonctionnalits supplmentaires permettant de dvelopper des applications dentreprise. Java ME est destin au dveloppement dapplications pour les priphriques tels que les tlphones cellulaires et les assistants personnels. Tous ces paquetages peuvent tre tlchargs depuis le site Web de Sun ladresse http://java.sun.com. A lheure o ces lignes sont crites, J2SE 5.0 est la version la plus rcente du Java SE. A moins que vous nayez une raison particulire dutiliser une version antrieure, utilisez donc cette version avec ce livre. Vous trouverez deux paquetages tlcharger dans le J2SE 5.0 : le JDK et le JRE. Le JDK est le kit de dveloppement Java. Il est ncessaire pour dvelopper des applications Java. Le JRE (Java runtime edition) ne permet que dexcuter des applications Java et non den dvelopper. Pour ce livre, vous aurez donc besoin de la distribution JDK du paquetage J2SE 5.0.

Compiler un programme Java

Info J2SE 5.0 et JDK 5.0 sont souvent aussi mentionns sous la rfrence JDK 1.5. Sun a dcid de changer officiellement le nom de la version 1.5 en lappelant 5.0.

Pour obtenir de laide lors de linstallation de la version la plus rcente du Java J2SE JDK, voir http://java.sun .com/j2se/1.5.0/install.html.

Compiler un programme Java


javac HelloWorld.java

Cet exemple compile le fichier source HelloWorld.java en code-octet. Le code-octet est la reprsentation Java indpendante de toute plate-forme des instructions dun programme. La sortie sera place dans le fichier HelloWorld.class. Lexcutable javac est inclus dans la distribution Java JDK. Il est utilis pour compiler les fichiers source Java que vous crivez dans des fichiers de classe Java. Un fichier de classe Java est une reprsentation en code-octet de la source Java compile. Pour plus dinformations sur la commande javac, consultez la documentation du JDK. De nombreuses options peuvent tre utilises avec javac qui ne sont pas traites dans ce livre. Pour la plupart de vos projets de programmation, lexception des petits programmes trs simples, vous utiliserez sans doute un EDI ou un outil comme Ant dApache pour raliser votre compilation. Si vous compilez autre

CHAPITRE 1 Les bases

chose quun trs petit projet avec des fichiers source minimaux, il est vivement conseill de vous familiariser avec Ant. Si vous connaissez loutil de compilation Make utilis par les programmeurs C, vous comprendrez limportance dAnt. Ant est en quelque sorte lquivalent de Make pour Java. Il permet de crer un script de compilation pour spcifier les dtails de la compilation dune application complexe puis de gnrer automatiquement lapplication complte laide dune seule commande. Pour plus dinformations sur Ant et pour tlcharger le programme, rendez-vous ladresse http://ant.apache.org.

Excuter un programme Java


javac HelloWorld.java // compilation du fichier source java HelloWorld // excution du code-octet

Dans cet exemple, nous utilisons dabord le compilateur javac pour compiler notre source Java dans un fichier HelloWorld.class. Ensuite, nous excutons le programme HelloWorld en utilisant la commande java laquelle nous passons le nom de la classe compile, HelloWorld. Notez que lextension .class nest pas incluse dans le nom qui est pass la commande java. Lexcutable java est inclus avec la distribution Java JDK ou la distribution Java JRE. Il est utilis pour excuter les fichiers de classe Java compils. Il fait office dinterprteur et compile en temps rel le code-octet en code natif excutable sur la plate-forme utilise. Lexcutable java est un lment de Java dpendant de la plate-forme dexcution. Chaque plate-forme qui supporte Java possde ainsi son propre excutable java compil spcifiquement pour elle. Cet lment est aussi appel la machine virtuelle.

Dfinir le chemin de classe

Dnir le chemin de classe


set CLASSPATH = /utilisateur/projets/classes java classpath = CLASSPATH%;classes/classfile.class;libs/stuff.jar

Le chemin de classe est utilis par lexcutable java et le compilateur java pour trouver les fichiers de classe compils et toutes les bibliothques empaquetes sous forme de fichiers JAR requis pour excuter ou compiler un programme. Les fichiers JAR sont le moyen standard dempaqueter des bibliothques dans une ressource prenant la forme dun fichier unique. Lexemple prcdent montre comment le chemin de classe peut tre dfini lors de lexcution dun programme Java en ligne de commande. Par dfaut, le chemin de classe est obtenu depuis la variable denvironnement systme CLASSPATH. Dans cet exemple, une classe spcifique appele classfile.class et situe dans le dossier classes est ajoute au chemin de classe dfini par la variable denvironnement. Une bibliothque appele stuff.jar situe dans le rpertoire libs est galement ajoute au chemin de classe. Si la variable denvironnement CLASSPATH nest pas dfinie et que loption classpath nest pas utilise, le chemin de classe par dfaut correspond au rpertoire courant. Si le chemin de classe est dfini avec lune de ces options, le rpertoire courant nest pas automatiquement inclus dans le chemin de classe. Il sagit l dune source frquente de problmes. Si vous dfinissez un chemin de classe, vous devez explicitement rajouter le rpertoire courant. Vous pouvez toutefois ajouter le rpertoire courant au chemin de classe en le spcifiant par "." dans le chemin de classe.

10

CHAPITRE 1 Les bases

Attention Notez que si toutes les classes se trouvent dans un rpertoire inclus dans le chemin de classe, il faut nanmoins que les fichiers JAR soient explicitement inclus dans le chemin de classe pour tre trouvs. Il ne suffit pas dinclure le rpertoire dans lequel ils rsident lintrieur du chemin de classe.

Les problmes lis aux chemins de classe sont trs courants chez les programmeurs novices comme chez les programmeurs expriments et peuvent souvent tre trs agaants rsoudre. Si vous prenez le temps de bien comprendre le fonctionnement des chemins de classe et de bien savoir les dfinir, vous devriez pouvoir viter ces problmes dans vos applications. Pour plus dinformations sur la configuration et lutilisation des chemins de classe, consultez la page http://java.sun.com/j2se/1.5.0/docs/tooldocs/ windows/classpath.html.

2
Interagir avec lenvironnement
Ce chapitre regroupe lensemble des exemples qui vous permettront dinteragir avec lenvironnement dexcution sur lequel votre application sexcute. Plusieurs dentre eux utilisent lobjet Java System, un objet Java central destin interagir avec lenvironnement qui entoure votre application Java. Il faut tre trs prudent lorsque vous utilisez cet objet et plus gnralement lorsque vous interagissez avec lenvironnement, car vous risquez par inadvertance de crer du code dpendant de votre plateforme. Lobjet System interagit avec lenvironnement et ce dernier est bien sr propre la plate-forme sur laquelle vous travaillez. Les effets de lutilisation dune mthode ou dune proprit de System sur une plate-forme peuvent ainsi ne pas tre les mmes sur lensemble des autres plates-formes.

12

CHAPITRE 2 Interagir avec lenvironnement

Obtenir des variables denvironnement


String envPath = System.getenv("PATH");

Cet exemple montre comment rcuprer une variable denvironnement avec la mthode System.getenv(). Cette mthode a t dconseille dans les versions du JDK comprises entre la version 1.2 et la version 1.4. Avec le JDK 1.5, Sun a pris une mesure exceptionnelle en revenant sur sa dcision et en rhabilitant cette mthode. Si vous utilisez une version du JDK pour laquelle cette mthode est dconseille, vous verrez des avertissements apparatre au moment de la compilation lorsque vous tentez dutiliser cette mthode. Les mthodes dconseilles ne doivent pas tre utilises dans les nouveaux projets de dveloppement mais restent gnralement prises en charge pour des raisons de compatibilit arrire. Il nexiste pas de garantie que les mthodes dconseilles continuent dtre prises en charge dans les versions futures du JDK, mais dans le cas prcis de cette mthode, il se trouve que la version la plus rcente du JDK la rhabilite : vous pouvez donc raisonnablement supposer quelle continuera dtre prise en charge. En gnral, on considre quil est de mauvais usage dutiliser des variables denvironnement dans les applications Java. Celles-ci dpendent en effet de la plate-forme, or le Java a justement pour vocation dtre indpendant de toute plate-forme. Certaines plates-formes Java (notamment Macintosh) ne proposent dailleurs pas de variable denvironnement. Votre code ne se comportera donc pas comme prvu dans ces environnements.

Dfinir et obtenir des proprits systme

13

Lexemple suivant montre comment obtenir et dfinir des proprits systme. Cette approche est prfrable celle qui consiste utiliser des variables denvironnement.

Dnir et obtenir des proprits systme


System.setProperty("timezone", "EasternStandardTime"); String zone = System.getProperty("timezone");

Les proprits systme sont des paires cl/valeur externes votre application Java. Lobjet Java System propose un mcanisme permettant de lire les noms et les valeurs de ces proprits systme externes depuis votre application Java. Lexemple prcdent montre comment dfinir et lire une proprit systme laide de lobjet Java System. Vous pouvez aussi rcuprer toutes les proprits systme dans un objet de proprits laide de linstruction suivante : Properties systemProps = System.getProperties(); Une autre mthode permet galement de rcuprer les noms des proprits systme. Le fragment de code suivant indique comment rcuprer tous les noms des proprits systme puis rcuprer chaque proprit avec son nom : Properties props = System.getProperties(); Enumeration propertyNames = props.propertyNames(); String key = ""; while (propertyNames.hasMoreElements()) { key = (String) propertyNames.nextElement(); System.out.println(key + "=" + props.getProperty(key)); }

14

CHAPITRE 2 Interagir avec lenvironnement

Parser des arguments en ligne de commande


java my_program arg1 arg2 arg3 public static void String arg1 = String arg2 = String arg3 = } main(String[] args) { args[0]; args[1]; args[2];

Dans cet exemple, nous stockons les valeurs de trois arguments en ligne de commande dans trois variables String spares, arg1, arg2 et arg3. Toutes les classes Java peuvent inclure une mthode main() excutable en ligne de commande. La mthode main() accepte un tableau String darguments en ligne de commande. Les arguments sont contenus dans le tableau dans lordre o ils sont entrs dans la ligne de commande. Pour les rcuprer, il vous suffit donc dextraire les lments du tableau des arguments pass la mthode main(). Si votre application utilise un grand nombre darguments en ligne de commande, il peut tre utile de passer du temps concevoir un parseur darguments en ligne de commande personnalis pour comprendre et grer les diffrents types darguments en ligne de commande, comme les paramtres un caractre, les paramtres avec des tirets (-), les paramtres immdiatement suivis par un autre paramtre li, etc.

Parser des arguments en ligne de commande

15

Info De nombreux exemples de processeurs darguments en ligne de commande peuvent tre trouvs sur Internet afin de gagner du temps. Deux bonnes bibliothques peuvent tre utilises pour dmarrer : http://jargs.sourceforge.net https://args4j.dev.java.net/ Ces deux bibliothques peuvent analyser les arguments dune ligne de commande complexe laide dune interface relativement simple.

3
Manipuler des chanes
En programmation, quel que soit le langage utilis, une grande partie des oprations ralises concerne la manipulation des chanes. A lexception des donnes numriques, presque toutes les donnes sont gres sous forme de chanes. Les donnes numriques sont dailleurs parfois elles-mmes manipules sous cette forme. On simagine difficilement comment il serait possible dcrire un programme complet sans utiliser la moindre chane. Les exemples de ce chapitre prsentent des tches courantes lies la manipulation des chanes. Le langage Java propose une excellente prise en charge des chanes. A la diffrence du langage C, les chanes sont des types prdfinis dans le langage Java. Celui-ci contient une classe String spcifiquement destine contenir les donnes de chane. En Java, les chanes ne doivent pas tre considres la manire de tableaux de caractres comme elles le sont en C.

18

CHAPITRE 3 Manipuler des chanes

Chaque fois que vous souhaitez reprsenter une chane en Java, vous devez utiliser la classe String et non un tableau. La classe String possde une proprit importante : une fois cre, la chane est immuable. Les objets Java String ne peuvent donc plus tre changs aprs quils sont crs. Vous pouvez attribuer le nom donn une chane un autre objet String, mais vous ne pouvez pas changer le contenu de la chane. Vous ne trouverez donc aucune mthode set dans la classe String. Si vous souhaitez crer une chane laquelle des donnes peuvent tre ajoutes (par exemple, dans une routine qui construit progressivement une chane), vous devez utiliser la classe StringBuilder dans le JDK 1.5 ou la classe StringBuffer dans les versions antrieures du Java, et non la classe String. Les classes StringBuilder et StringBuffer sont muables : leur contenu peut tre modifi. Il est trs courant de construire des chanes en utilisant la classe StringBuilder ou StringBuffer et de passer ou stocker des chanes en utilisant la classe String.

Comparer des chanes


boolean result = str1.equals(str2); boolean result2 = str1.equalsIgnoreCase(str2);

La valeur de result et result2 doit tre true si les chanes ont le mme contenu. Si leur contenu est diffrent, result et result2 valent false. La premire mthode, equals(), tient compte de la casse des caractres dans les chanes. La seconde, equalsIgnoreCase(), ignore la casse des caractres et retourne true si le contenu est identique indpendamment de la casse.

Comparer des chanes

19

Les oprations de comparaison de chanes sont une source courante de bogues pour les programmeurs dbutants en Java. Ces derniers sefforcent souvent de comparer leurs chanes avec loprateur de comparaison ==. Or ce dernier compare les rfrences dobjet et non le contenu des objets. Deux objets chane qui contiennent les mmes donnes de chane mais correspondent des instances dobjet physiquement distinctes ne sont ds lors pas considrs comme gaux selon cet oprateur. La mthode equals() de la classe String fait porter la comparaison sur le contenu de la chane et non sur sa rfrence dobjet. En gnral, il sagit de la mthode de comparaison souhaite pour les comparaisons de chanes. Voyez lexemple suivant : String name1 = new String("Timmy"); String name2 = new String("Timmy"); if (name1 == name2) { System.out.println("The strings are equal."); } else { System.out.println("The strings are not equal."); } La sortie obtenue aprs lexcution de ces instructions est la suivante : The strings are not equal. A prsent, utilisez la mthode equals() et observez le rsultat : String name1 = new String("Timmy"); String name2 = new String("Timmy"); if (name1.equals(name2)) { System.out.println("The strings are equal.");

20

CHAPITRE 3 Manipuler des chanes

} else { System.out.println("The strings are not equal."); }

La sortie obtenue aprs lexcution de ces instructions est la suivante : The strings are equal. La mthode compareTo() est une autre mthode apparente de la classe String. Elle compare alphabtiquement deux chanes en retournant une valeur entire : positive, ngative ou gale 0. La valeur 0 nest retourne que si la mthode equals() est value true pour les deux chanes. Une valeur ngative est retourne si la chane sur laquelle la mthode est appele prcde dans lordre alphabtique celle qui est passe en paramtre la mthode. Une valeur positive est retourne si la chane sur laquelle la mthode est appele suit dans lordre alphabtique celle qui est passe en paramtre. En fait, la comparaison seffectue en fonction de la valeur Unicode de chaque caractre dans les chanes compares. La mthode compareTo() possde galement une mthode compareToIgnoreCase() correspondante qui opre de la mme manire mais en ignorant la casse des caractres. Considrez lexemple suivant : String name1="Camden"; String name2="Kerry"; int result = name1.compareTo(name2); if (result == 0) { System.out.println("The names are equal."); }

Rechercher et rcuprer des sous-chanes

21

else if (result > 0) { System.out.println( "name2 comes before name1 alphabetically."); } else if (result < 0) { System.out.println( "name1 comes before name2 alphabetically."); }

La sortie de ce code est : name1 comes before name2 alphabetically.

Rechercher et rcuprer des sous-chanes


int result = string1.indexOf(string2); int result = string1.indexOf(string2, 5);

Dans la premire mthode, la valeur de result contient lindex de la premire occurrence de string2 lintrieur de string1. Si string2 nest pas contenu dans string1, la valeur -1 est retourne. Dans la seconde mthode, la valeur de result contient lindex de la premire occurrence de string2 lintrieur de string1 qui intervient aprs le cinquime caractre dans string1. Le second paramtre peut tre nimporte quel entier valide suprieur 0. Si la valeur est suprieure la longueur de string1, la valeur -1 est retourne. Outre rechercher une sous-chane dans une chane, il peut arriver que vous sachiez o se trouve la sous-chane et que vous souhaitiez simplement latteindre. La mthode

22

CHAPITRE 3 Manipuler des chanes

substring() de la chane vous permet de latteindre. Cette

mthode est surcharge, ce qui signifie quil existe plusieurs moyens de lappeler. Le premier consiste lui passer simplement un index de dpart. Cette mthode retourne une sous-chane qui commence lindex de dpart et stend jusqu la fin de la chane. Lautre moyen dutiliser substring() consiste lappeler avec deux paramtres un index de dpart et un index de fin. String string1 = "My address is 555 Big Tree Lane"; String address = string1.substring(14); System.out.println(address); Ce code produit la sortie suivante : 555 Big Tree Lane Le premier caractre 5 se trouve la position 14 de la chane. Il sagit donc du dbut de la sous-chane. Notez que les chanes sont toujours indexes en commenant 0 et que le dernier caractre se trouve lemplacement (longueur de la chane) - 1.

Traiter une chane caractre par caractre


for (int index = 0; index < string1.length(); index++) { char aChar = string1.charAt(index); }

La mthode charAt()permet dobtenir un unique caractre de la chane lindex spcifi. Les caractres sont indexs en commenant 0, de 0 (longueur de la chane) - 1.

Renverser une chane par caractre

23

Cet exemple parcourt en boucle chaque caractre contenu dans string1. Il est aussi possible de procder en utilisant la classe StringReader, comme ceci : StringReader reader = new StringReader(string1); int singleChar = reader.read(); Avec ce mcanisme, la mthode read() de la classe StringReader retourne un caractre la fois, sous forme dentier. A chaque fois que la mthode read() est appele, le caractre suivant de la chane est retourn.

Renverser une chane par caractre


String letters = "ABCDEF"; StringBuffer lettersBuff = new StringBuffer(letters); String lettersRev = lettersBuff.reverse().toString();

La classe StringBuffer contient une mthode reverse() qui retourne un StringBuffer contenant les caractres du StringBuffer original, mais inverss. Un objet StringBuffer peut aisment tre converti en objet String laide de la mthode toString() de lobjet StringBuffer. En utilisant temporairement un objet StringBuffer, vous pouvez ainsi produire une seconde chane avec les caractres dune chane dorigine, en ordre invers. Si vous utilisez le JDK 1.5, vous pouvez utiliser la classe
StringBuilder au lieu de la classe StringBuffer.StringBuilder possde une API compatible avec la classe StringBuffer. Elle propose de meilleures performances,

mais ses mthodes ne sont pas synchronises. Elle nest donc pas thread-safe. En cas de multithreading, vous devez continuer utiliser la classe StringBuffer.

24

CHAPITRE 3 Manipuler des chanes

Renverser une chane par mot


String test = "Reverse this string"; Stack stack = new Stack(); StringTokenizer strTok = new StringTokenizer(test); while(strTok.hasMoreTokens()) { stack.push(strTok.nextElement()); } StringBuffer revStr = new StringBuffer(); while(!stack.empty()) { revStr.append(stack.pop()); revStr.append(" "); } System.out.println("Original string: " + test); System.out.println("\nReversed string: " + revStr);

La sortie de ce fragment de code est la suivante : Original string: Reverse this string Reversed string: string this Reverse Comme vous pouvez le voir, le renversement dune chane par mot est plus complexe que le renversement dune chane par caractre. Cest quil existe un support intgr dans Java pour le renversement par caractre, et non pour le renversement par mot. Pour raliser cette dernire tche, nous utilisons les classes StringTokenizer et Stack. Avec StringTokenizer, nous parsons chaque mot de la chane et le poussons dans notre pile. Une fois la chane entire traite, nous parcourons la pile en boucle en dpilant chaque mot et en lajoutant un StringBuffer qui stocke la chane inverse.

Convertir une chane en majuscules ou en minuscules

25

Dans la pile, le dernier lment entr est par principe le premier sorti une proprit baptise LIFO (last in, first out) que nous exploitons pour effectuer linversion. Consultez l'exemple trait dans la section "Parser une chane spare par des virgules" de ce chapitre pour dautres utilisations de la classe StringTokenizer.
Info Nous nen traiterons pas ici, mais un nouvel ajout du JDK 1.5 peut vous intresser : la classe Scanner. Cette classe est un analyseur de texte lmentaire permettant de parser des types primitifs et des chanes laide dexpressions rgulires.

Convertir une chane en majuscules ou en minuscules


String string = "Contains some Upper and some Lower."; String string2 = string.toUpperCase(); String string3 = string.toLowerCase();

Ces deux mthodes transforment une chane en majuscules ou en minuscules uniquement. Elles retournent toutes deux le rsultat transform. Ces mthodes naffectent pas la chane dorigine. Celle-ci reste intacte avec une casse mixte. Ces mthodes peuvent notamment tre utiles lors du stockage dinformations dans une base de donnes, par exemple si vous souhaitez stocker des valeurs de champ en majuscules ou en minuscules uniquement. Grce ces mthodes, lopration de conversion est un jeu denfant.

26

CHAPITRE 3 Manipuler des chanes

La conversion de la casse est galement utile pour la gestion des interfaces dauthentification des utilisateurs. Le champ dID de lutilisateur est normalement considr comme tant un champ qui ne doit pas tenir compte de la casse, alors que le champ de mot de passe en tient compte. Lors de la comparaison de lID utilisateur, vous pouvez ainsi convertir lID en majuscules ou en minuscules puis le comparer une valeur stocke dans la casse approprie. Vous pouvez aussi utiliser la mthode equalsIgnoreCase() de la classe String, qui ralise une comparaison sans tenir compte de la casse.

Supprimer les espaces au dbut et la n dune chane


String result = str.trim();

La mthode trim() supprime les espaces de dbut et de fin dune chane et retourne le rsultat. La chane originale reste inchange. Sil ny a pas despace de dbut ou de fin supprimer, la chane dorigine est retourne. Les espaces et les caractres de tabulation sont supprims. Cette mthode est trs utile lorsquil sagit de comparer des entres saisies par lutilisateur avec des donnes existantes. Bien des programmeurs se sont creus la tte de nombreuses heures en se demandant pourquoi les donnes saisies ntaient pas identiques la chane stocke et se sont finalement aperu que la diffrence ne tenait qu un simple espace blanc la fin de la chane. La suppression des espaces avant les comparaisons limine entirement ce problme.

Parser une chane spare par des virgules

27

Parser une chane spare par des virgules


String str = "tim,kerry,timmy,camden"; String[] results = str.split(",");

La mthode split() de la classe String accepte une expression rgulire comme unique paramtre et retourne un tableau dobjets String dcompos selon les rgles de lexpression rgulire passe. Le parsing des chanes spares par des virgules devient ainsi un jeu denfant. Dans cet exemple, nous passons simplement une virgule la mthode split() et obtenons un tableau de chanes contenant les donnes spares par des virgules. Le tableau de rsultat de notre exemple contient ainsi les donnes suivantes : results[0] = tim results[1] = kerry results[2] = timmy results[3] = camden La classe StringTokenizer est elle aussi utile pour dcomposer des chanes. Lexemple prcdent peut tre repris avec cette classe au lieu de la mthode split() : String str = "tim,kerry,timmy,Camden"; StringTokenizer st = new StringTokenizer(str, ","); while (st.hasMoreTokens()) { System.out.println(st.nextToken()); }

28

CHAPITRE 3 Manipuler des chanes

Cet exemple de code imprime chacun des noms contenus dans la chane dorigine (str) sur une ligne spare, comme ceci : tim kerry timmy camden Notez que les virgules sont supprimes (elles ne sont pas imprimes). La classe StringTokenizer peut tre construite avec un, deux ou trois paramtres. Lorsquelle est appele avec un seul paramtre, le paramtre correspond la chane diviser. Dans ce cas, le dlimiteur utilis correspond aux limites naturelles de mot par dfaut. Le tokenizer utilise ainsi le jeu de dlimiteurs " \t\n\r\f" (le caractre despace, le caractre de tabulation, le caractre de nouvelle ligne, le caractre de retour chariot et le caractre davancement de page). Le deuxime moyen de construire un objet StringTokenizer consiste passer deux paramtres au constructeur. Le premier paramtre correspond alors la chane dcomposer et le second la chane contenant les dlimiteurs en fonction desquels la chane doit tre divise. Ce paramtre vient remplacer les dlimiteurs par dfaut. Pour finir, vous pouvez passer un troisime argument au constructeur StringTokenizer qui indique si les dlimiteurs doivent tre retourns sous forme de jetons ou supprims. Ce paramtre est boolen. Si vous passez la valeur true, les dlimiteurs sont retourns sous forme de jetons. Par dfaut, le paramtre vaut false. Il supprime les dlimiteurs et ne les traite pas comme des jetons.

Parser une chane spare par des virgules

29

Examinez aussi les exemples du Chapitre 6. Avec lajout du support des expressions rgulires en Java propos par le JDK 1.4, il devient souvent possible dutiliser des expressions rgulires au lieu de la classe StringTokenizer. La documentation JavaDoc officielle stipule que la classe StringTokenizer est une classe hrite dont lusage doit tre dconseill dans le nouveau code. Dans la mesure du possible, utilisez donc la mthode split() de la classe String ou le paquetage Java pour les expressions rgulires.

4
Travailler avec des structures de donnes
On appelle "structure de donnes" un dispositif servant organiser les donnes utilises par un programme. Chaque fois que vous travaillez avec des groupes dlments de donnes similaires, il est judicieux dutiliser une structure de donnes. Le Java offre une excellente gestion des diffrents types de structures de donnes, dont les tableaux, les listes, les dictionnaires et les ensembles. La plupart des classes Java servant travailler avec les structures de donnes sont livres dans le framework Collections, une architecture unifie pour la reprsentation et la manipulation de collections ou de structures de donnes. Les classes de structure de donnes les plus couramment utilises sont ArrayList et HashMap. La plupart des exemples de ce chapitre sy rfrent. Lexpression "structure de donnes" peut sappliquer la manire dont les donnes sont ordonnes dans un fichier ou une base de donnes tout autant quen mmoire. Tous les exemples de ce chapitre traitent des structures de donnes en mmoire.

32

CHAPITRE 4 Travailler avec des structures de donnes

Info Sun met disposition un document (en anglais) qui offre une bonne vue densemble du framework Collections et propose des didacticiels sur lutilisation des diffrentes classes. Pour consulter ce document, rendez-vous ladresse suivante : http:// java.sun.com/j2se/1.5.0/docs/guide/collections/index.html.

Redimensionner un tableau
// Utiliser un ArrayList List myArray = new ArrayList();

En Java, les tableaux dobjets normaux ou de types primitifs ne peuvent pas tre redimensionns de manire dynamique. Si vous souhaitez quun tableau soit agrandi par rapport sa dclaration dorigine, vous devez dclarer un nouveau tableau plus grand, puis copier le contenu du premier tableau dans le nouveau. La procdure peut prendre la forme suivante : int[] tmp = new int[myArray.length + 10]; System.arraycopy(myArray, 0, tmp, 0, myArray.length); myArray = tmp; Dans cet exemple, nous souhaitons agrandir la taille dun tableau dentiers appel myArray afin de lui ajouter dix lments. Nous crons donc un nouveau tableau appel tmp et linitialisons en lui attribuant la longueur de myArray + 10. Nous utilisons ensuite la mthode System.arrayCopy() pour copier le contenu de myArray dans le tableau tmp. Pour finir, nous positionnons myArray de manire ce quil pointe sur le tableau tmp nouvellement cr. En gnral, la meilleure solution pour ce type de problme consiste utiliser un objet ArrayList au lieu dun tableau dobjets classique. Lobjet ArrayList peut contenir

Parcourir une collection en boucle

33

nimporte quel type dobjet. Son principal intrt tient ce quil se redimensionne automatiquement selon les besoins. Lorsque vous utilisez un ArrayList, vous navez plus vous soucier de la taille de votre tableau en vous demandant si vous risquez de manquer de place. Limplmentation ArrayList est en outre bien plus efficace que la mthode prcdente qui consiste copier le tableau redimensionner dans un nouveau tableau. Lobjet ArrayList fait partie du paquetage java.util.

Parcourir une collection en boucle


// Pour un ensemble ou une liste // collection est l'objet set ou list for (Iterator it= collection.iterator(); it.hasNext(); ) { Object element = it.next(); } // Pour les cls d'un dictionnaire for (Iterator it = map.keySet().iterator(); it.hasNext(); ){ Object key = it.next(); } // Pour les valeurs d'un dictionnaire for (Iterator it = map.values().iterator(); it.hasNext(); ){ Object value = it.next(); } // Pour les cls et les valeurs d'un dictionnaire for (Iterator it = map.entrySet().iterator(); it.hasNext(); ) { Map.Entry entry = (Map.Entry)it.next(); Object key = entry.getKey(); Object value = entry.getValue(); }

34

CHAPITRE 4 Travailler avec des structures de donnes

Le paquetage java.util contient une classe Iterator qui facilite le parcours en boucle des collections. Pour parcourir en boucle un objet collection, vous devez dabord obtenir un objet Iterator en appelant la mthode iterator() de lobjet collection. Lorsque vous avez lobjet Iterator, il ne reste plus qu le parcourir pas pas avec la mthode next(). Cette mthode retourne llment suivant de la collection. La mthode next() retourne un type Object gnrique. Vous devez donc transtyper la valeur de retour afin de lui attribuer le type attendu. La mthode hasNext() vous permet quant elle de vrifier sil existe dautres lments qui nont pas encore t traits. En combinant ces deux mthodes, vous pouvez ainsi aisment crer une boucle for pour parcourir un un chacun des lments dune collection, comme le montre lexemple prcdent. Lexemple prcdent indique aussi comment parcourir en boucle un ensemble ou une liste, les cls dun dictionnaire, les valeurs dun dictionnaire et les cls et les valeurs dun dictionnaire.
Info Les itrateurs peuvent tre utiles pour exposer des collections via une API. Lavantage quapporte lexposition des donnes laide dun itrateur tient ce que le code appelant na pas se soucier de la manire dont les donnes sont stockes. Cette implmentation permet de changer le type de collection sans avoir modifier lAPI.

Crer une collection mappe

35

Crer une collection mappe


HashMap map = map.put(key1, map.put(key2, map.get(key3, new HashMap(); obj1); obj2); obj3);

Cet exemple utilise un HashMap pour crer une collection mappe dobjets. Le HashMap possde une mthode put() qui prend deux paramtres. Le premier est une valeur de cl et le second lobjet que vous souhaitez stocker dans le dictionnaire. Dans cet exemple, nous stockons donc trois objets (obj1, obj2 et obj3) en les indexant avec des cls (respectivement key1, key2 et key3). La classe HashMap est lune des classes Java les plus couramment utilises. Dans un HashMap, les objets placs dans un dictionnaire doivent tous tre du mme type de classe. Si obj1 est un objet String, obj2 et obj3 doivent donc galement tre des objets String. Pour rcuprer les objets placs dans la collection, vous utilisez la mthode get() du HashMap. Elle prend un unique paramtre correspondant la cl de llment rcuprer. Si llment est trouv, il est retourn sous forme dobjet gnrique Object : il faut donc le transtyper pour lui attribuer le type dsir. Si llment que vous tentez de rcuprer nexiste pas, la valeur null est retourne.
Info Le JDK 1.5 introduit une nouvelle fonctionnalit du langage, les gnriques, permettant de rcuprer des lments dun HashMap sans avoir raliser de transtypage. Sun propose un excellent article sur lutilisation des gnriques ladresse suivante : http://java.sun.com/developer/technicalArticles/J2SE /generics/index.html.

36

CHAPITRE 4 Travailler avec des structures de donnes

Les objets utiliss comme valeurs de cl dans un HashMap doivent implmenter les mthodes equals() et hashCode(). Ces mthodes sont utilises par limplmentation HashMap pour retrouver les lments dans le dictionnaire. Si elles ne sont pas implmentes dans un objet utilis comme valeur de cl, les objets cls sont retrouvs en fonction de leur identit uniquement. Dans ce cas, pour trouver une cl concordante, vous devrez passer linstance dobjet elle-mme lorsque vous essayerez de rcuprer un objet : a priori, ce nest pas le but recherch !

Stocker une collection


// Trier un tableau int[] myInts = {1,5,7,8,2,3}; Arrays.sort(myInts); // Trier une liste List myList = new ArrayList(); myList.put(obj1); myList.put(obj2); Collections.sort(myList);

La classe Arrays est une classe du paquetage java.util contenant un grand nombre de mthodes statiques servant manipuler des tableaux. La plus utile dentre elles est sans doute la mthode sort(). Cette mthode prend un tableau dobjets ou de types primitifs et des index de dbut et de fin. Lindex de dbut spcifie lindex du premier lment trier et lindex de fin celui du dernier lment trier. Les primitifs sont tris par ordre croissant. Lorsque cette mthode est utilise pour trier des objets, tous les objets doivent implmenter linterface Comparable, dfaut de quoi un objet Comparator peut tre pass.

Stocker une collection

37

Dans lexemple prcdent, nous commenons avec un tableau dentiers de type int. Nous passons ce tableau la mthode Arrays.sort() qui le trie. Notez bien que cest le tableau lui-mme qui est pass : il est donc directement tri et modifi. La mthode sort() ne retourne pas de nouveau tableau tri : son type de retour est void. La classe Collections, autre classe du paquetage java.util, contient des mthodes statiques qui oprent sur dautres objets de collection. La mthode sort() prend un objet List en entre et trie les lments dans la liste par ordre croissant, selon lordre naturel des lments. Comme avec la mthode sort() de lobjet Arrays, tous les lments dans lobjet List pass la mthode doivent implmenter linterface Comparable dfaut de quoi un objet Comparator peut tre pass avec lobjet List. La liste passe la mthode sort() est elle-mme modifie. Dans la seconde partie de notre exemple, nous crons un objet ArrayList et utilisons la mthode Collections.sort() pour le trier. Dans cet exemple, aucun objet Comparator na t pass, aussi les objets obj1 et obj2 doivent imprativement implmenter linterface Comparable. Si lordre de tri par dfaut ne vous convient pas, vous pouvez implmenter linterface Comparator pour dfinir votre propre mcanisme de tri. Le comparateur que vous dfinissez peut ensuite tre pass comme second argument la mthode sort() de la classe Collections ou Arrays. En plus des classes que nous venons de citer, le framework Collections contient des classes dont le tri est inhrent, comme les objets TreeSet et TreeMap. Si vous utilisez ces classes, les lments sont automatiquement tris lorsquils sont placs dans la collection. Dans le cas dun TreeSet, les lments sont tris par ordre croissant

38

CHAPITRE 4 Travailler avec des structures de donnes

daprs linterface Comparable ou daprs le Comparator fourni au moment de la cration. Dans le cas dun TreeMap, les lments sont tris par ordre croissant de cl daprs linterface Comparable ou daprs le Comparator fourni au moment de la cration.

Trouver un objet dans une collection


// Trouver un objet dans un ArrayList int index = myArrayList.indexOf(myStringObj); // Trouver un objet par valeur dans un HashMap myHashMap.containsValue(myStringObj); // Trouver un objet par cl dans un HashMap myHashMap.containsKey(myStringObj);

Ces exemples montrent comment retrouver des objets dans les collections les plus couramment utiliss : ArrayList et HashMap. La mthode indexOf() de lobjet ArrayList permet de retrouver la position dans le tableau laquelle se trouve un objet particulier. Si lobjet pass la mthode indexOf() nest pas retrouv, la mthode retourne -1. Lobjet HashMap indexe les lments par objets et non par valeurs entires comme le fait lobjet ArrayList. Les mthodes containsValue() ou containsKey() peuvent tre utilises pour dterminer si le HashMap contient lobjet pass comme valeur ou comme cl dans le dictionnaire. Elles retournent une valeur boolenne. Deux autres mthodes, binarySearch() et contains(), permettent galement de retrouver des objets dans des collections. La mthode binarySearch() est une mthode

Trouver un objet dans une collection

39

des classes utilitaires Arrays et Collections. Elle effectue une recherche dans un tableau selon lalgorithme de recherche binaire. Le tableau doit tre tri avant dappeler la mthode binarySearch() de la classe Arrays. Sans cela, les rsultats sont indfinis. Le tri du tableau peut tre ralis avec la mthode Arrays.sort(). Si le tableau contient plusieurs lments possdant la valeur spcifie comme valeur de recherche, rien ne permet de dterminer celui qui sera retrouv. Selon la mme logique, la mthode binarySearch() de la classe Collections ne doit tre utilise que sur une collection dj trie par ordre croissant selon lordre naturel de ses lments. Ce tri peut tre ralis avec la mthode Collections.sort(). Comme pour les tableaux, lemploi de binarySearch() sur une collection non trie produit des rsultats indfinis. Sil existe plusieurs lments correspondant lobjet recherch, rien ne permet non plus de dterminer celui qui sera retrouv. Lorsque la collection nest pas dj trie, il peut tre prfrable dutiliser la mthode indexOf() plutt que de raliser le tri (sort()) puis la recherche binaire (binarySearch()). Lopration de tri (sort()) peut tre coteuse dans le cas de certaines collections. Lexemple suivant utilise la mthode binarySearch() pour effectuer une recherche dans un tableau dentiers : int[] myInts = new int[]{7, 5, 1, 3, 6, 8, 9, 2}; Arrays.sort(myInts); int index = Arrays.binarySearch(myInts, 6); System.out.println("Value 6 is at index: " + index); Ce code produit la sortie suivante : The value 6 is at index 4.

40

CHAPITRE 4 Travailler avec des structures de donnes

La classe ArrayList possde galement une mthode contains() qui peut tre utilise pour vrifier si un objet donn est membre dun ArrayList donn.

Convertir une collection en un tableau


// Convertir un ArrayList en un tableau dobjets Object[] objects = aArrayList.toArray(); // Convertir un HashMap en un tableau d'objets Object[] mapObjects = aHashMap.entrySet().toArray();

Comme le montre cet exemple, il est assez simple en Java de convertir une collection telle quun ArrayList ou un HashMap en un tableau dobjets standard. Lobjet ArrayList possde une mthode toArray() qui retourne un tableau dobjets. La conversion dun HashMap en un tableau est lgrement diffrente. Il faut dabord obtenir les valeurs stockes dans le HashMap sous forme de tableau en utilisant la mthode entrySet(). La mthode entrySet() retourne les valeurs de donnes sous forme de Set Java. Une fois que lobjet Set est obtenu, nous pouvons appeler la mthode toArray() pour rcuprer un tableau contenant les valeurs stockes dans le HashMap.

5
Dates et heures
La plupart des programmes Java sont immanquablement conduits devoir grer des dates et des heures un moment ou un autre. Fort heureusement, la gestion des dates et des heures est fort bien intgre Java. Trois classes principales sont utilises dans la plupart des programmes pour stocker et manipuler les heures et les dates : java.util.Date, java.sql.Date et java.util.Calendar. Bon nombre des mthodes de la classe java.util.Date sont maintenant dconseilles : vous devez donc viter de les utiliser pour vos nouveaux projets de dveloppement. Les mthodes dconseilles concernent pour la plupart la cration et la manipulation des dates. Dans le cas de ces oprations, il est prfrable dutiliser le mcanisme de la classe java.util.Calendar. Les conversions entre les objets Date et Calendar sont faciles. Si vous prfrez passer vos dates sous forme dobjets Date, il est donc parfaitement possible dviter les mthodes dconseilles. Vous devez alors simplement convertir vos dates en objets Calendar au moment de les manipuler. Lun des exemples de ce chapitre montre comment effectuer la conversion entre les objets Date et les objets Calendar.

42

CHAPITRE 5 Dates et heures

Retrouver la date daujourdhui


Date today = new java.util.Date(); System.out.println("Todays Date is " + today.toString());

Il est impratif que vous soyez familiaris avec lobjet Date du paquetage java.util si vos programmes traitent avec des dates et des heures, car cet objet est trs frquemment utilis. Il permet notamment de rcuprer trs simplement la date et lheure courantes. Lorsque vous crez une instance de lobjet Date, celle-ci est initialise avec lheure et la date courantes. La classe Calendar propose une autre mthode pour rcuprer la date et lheure courantes, comme ceci : Calendar cal = Calendar.getInstance(); Cette ligne produit un objet Calendar nomm cal et linitialise avec la date et lheure courantes.

Conversion entre les objets Date et Calendar


// Conversion de Date Calendar Date myDate = new java.util.Date(); Calendar myCal = Calendar.getInstance(); myCal.setTime(myDate); // Conversion de Calendar Date Calendar newCal = Calendar.getInstance(); Date newDate = newCal.getTime();

En travaillant avec des heures et des dates, vous constaterez souvent quil est ncessaire deffectuer une conversion entre des objets Java Date et Calendar. Cette tche est

Conversion entre les objets Date et Calendar

43

heureusement trs simple, comme en atteste lexemple prcdent. Lobjet Calendar possde une mthode setTime() qui prend un objet java.util.Date en entre et positionne lobjet Calendar en lui attribuant la date et lheure contenues dans lobjet Date pass. Pour la conversion inverse, vous pouvez utiliser la mthode getTime() de la classe Calendar qui retourne la date et lheure du calendrier sous forme dobjet java.util.Date. La plupart des applications Java se servent des classes Date et Calendar. De l limportance quil y a se familiariser avec le processus de conversion dun type vers lautre. Il est conseill de crer des mthodes utilitaires pour raliser ces conversions afin de pouvoir les utiliser depuis nimporte quel emplacement du code au moyen dun simple appel de mthode. Voici des mthodes simples pour la conversion des objets Calendar en objets Date et des objets Date en objets Calendar : public static Date calToDate(Calendar cal) { return cal.getTime(); }
public static Calendar dateToCal(Date date) { Calendar myCal = Calendar.getInstance(); myCal.setTime(date); return myCal; }

44

CHAPITRE 5 Dates et heures

Imprimer une date/une heure dans un format spci


Date todaysDate = new java.util.Date(); SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss"); String formattedDate = formatter.format(todaysDate); System.out.println("Todays Date and Time is: " + formattedDate);

Le Java contient des classes de formatage qui peuvent tre utilises pour appliquer une date un format dsir. La classe la plus couramment utilise pour le formatage des dates est la classe SimpleDateFormat. Elle prend une chane de format en entre de son constructeur et retourne un objet de format qui peut tre utilis ensuite pour formater des objets Date. La mthode format() de lobjet SimpleDateFormat retourne une chane contenant la reprsentation formate de la Date passe en paramtre. Voici la sortie de lexemple prcdent : Todays Date and Time is: jeu., 04 janv. 2007 16:48:38 La chane de format passe au constructeur SimpleDateFormat peut paratre un peu obscure si vous ne connaissez pas les codes de formatage utiliser. Le Tableau 5.1 prsente les codes qui peuvent tre passs au constructeur de SimpleDateFormat. Dans notre exemple, nous avons utilis la chane de format suivante : "EEE, dd MMM yyyy HH:mm:ss" Dcomposons cette chane en nous rfrant au Tableau 5.1, afin de comprendre le format demand : b EEE : reprsentation sur trois caractres du jour de la semaine (par exemple, Mar). b , : place une virgule dans la sortie.

Imprimer une date/une heure dans un format spcifi

45

b dd : reprsentation sur deux caractres du jour du mois (01 31). b MMM : reprsentation sur trois caractres du mois de lanne (par exemple, Jul). b yyyy : reprsentation sur quatre caractres de lanne (par exemple, 2006). b HH:mm:ss : heure, minutes et secondes, spares par des deux-points (par exemple, 11:18:33). Ces lments combins produisent la chane de date suivante : jeu., 04 janv. 2007 16:48:38
Tableau 5.1 : Codes de format de date et dheure
Lettre Composant de date ou dheure Prsentation Exemples

G y M w W D d F E a

Dsignateur dre Anne Mois de lanne

Texte Anne Mois

AD 1996 ; 96 Juillet ; Jul ; 07 27 2 189 10 2 Mardi ; Mar PM

Semaine de lanne Nombre Semaine du mois Jour de lanne Jour du mois Jour de la semaine dans le mois Jour de la semaine Marqueur A.M./P.M. Nombre Nombre Nombre Nombre Texte Texte

46

CHAPITRE 5 Dates et heures

Tableau 5.1 : Codes de format de date et dheure (suite)


Lettre Composant de date ou dheure Prsentation Exemples

H k K h m s S z

Heure du jour (0 23) Heure du jour (1 24)

Nombre Nombre

0 24 0 12 30 55 978

Nombre Heure au format A.M./P.M. (0 11) Nombre Heure au format A.M./P.M. (1 12) Minutes dans lheure Secondes dans la minute Millisecondes Fuseau horaire Nombre Nombre Nombre

Fuseau horaire Pacific Standard Time ; gnral PST ; GMT-08:00 Fuseau horaire -0800 RFC 822

Fuseau horaire

En plus de crer vos propres chanes de format, vous pouvez utiliser lune des chanes de format prdfinies avec les mthodes getTimeInstance(), getDateInstance() ou getDateTimeInstance() de la classe DateFormat. Par exemple, le code suivant retourne un objet formateur qui utilisera un format de date pour vos paramtres rgionaux par dfaut : DateFormat df = DateFormat.getDateInstance();

Parser des chanes en dates

47

Le formateur df peut ensuite tre utilis exactement comme nous avons utilis lobjet SimpleDateFormat dans notre exemple prcdent. Consultez la documentation JavaDoc disponible pour la classe DateFormat pour obtenir des informations dtailles sur les objets de formatage dheure et de date standard disponibles ladresse http://java.sun.com/j2se/1.5.0/docs/api/java/text/ DateFormat.html.

Parser des chanes en dates


String dateString = "January 12, 1952 or 3:30:32pm"; DateFormat df = DateFormat.getDateInstance(); Date date = df.parse(dateString);

Lobjet DateFormat est utilis pour parser un objet String et obtenir un objet java.util.Date. La mthode getDateInstance() cre un objet DateFormat avec le format de date standard de votre pays. Vous pouvez ensuite utiliser la mthode parse() de lobjet DateFormat retourn pour parser votre chane de date et obtenir un objet Date, comme le montre cet exemple. La mthode parse() accepte aussi un second paramtre qui spcifie la position dans la chane partir de laquelle lanalyse doit tre effectue. Les classes java.sql.Date, java.sql.Time et java.sql .Timestamp contiennent une mthode statique appele valueOf() qui peut galement tre utilise pour parser des chanes de date simples au format aaaa-mm-jj. Elles sont trs utiles pour convertir en objets Date des dates utilises dans des chanes SQL avec des objets JDBC.

48

CHAPITRE 5 Dates et heures

Ces techniques sont utiles pour convertir des donnes de date entres par lutilisateur en objets Date Java pour un traitement ultrieur dans votre application. Vous pouvez rcuprer les dates entres par lutilisateur sous forme de chane et les convertir en objets Date laide de ces techniques.

Additions et soustractions avec des dates ou des calendriers


// Arithmtique de dates utilisant des objets Date Date date = new Date(); long time = date.getTime(); time += 5*24*60*60*1000; Date futureDate = new Date(time); // Arithmtique de dates utilisant des objets Calendar Calendar nowCal = Calendar.getInstance(); nowCal.add(Calendar.DATE, 5);

Si vous utilisez un objet Date, la technique dajout ou de soustraction des dates consiste convertir dabord lobjet en une valeur long en utilisant la mthode getTime() de lobjet Date. La mthode getTime() retourne lheure mesure en millisecondes depuis le dbut de "lre" UNIX (1er janvier 1970, 00 h 00 s 00 ms GMT). Ensuite, vous devez raliser lopration arithmtique avec des valeurs long et reconvertir le rsultat en objet Date. Dans lexemple prcdent, nous ajoutons 5 jours lobjet Date. Nous convertissons les 5 jours en millisecondes en multipliant 5 par le nombre dheures dans une journe (24), le nombre de minutes dans une heure (60), le nombre de secondes dans une minute (60) et finalement par 1 000 pour convertir les secondes en millisecondes.

Calculer la diffrence entre deux dates

49

Les oprations arithmtiques de date peuvent tre ralises directement sur des objets Calendar en utilisant la mthode add(). Cette mthode prend deux paramtres, un champ et une quantit, tous deux de type int. La quantit spcifie est ajoute au champ spcifi. Le champ peut correspondre nimporte quel champ de date valide, comme un jour, une semaine, un mois, une anne, etc. Pour soustraire une heure, vous devez utiliser une valeur ngative. En positionnant le paramtre de champ la constante Calendar approprie, vous pouvez directement ajouter ou soustraire des jours, des semaines, des mois, des annes, etc. La seconde partie de lexemple prcdent montre comment ajouter 5 jours un objet Calendar.

Calculer la diffrence entre deux dates


long time1 = date1.getTime(); long time2 = date2.getTime(); long diff = time2 time1; System.out.println("Difference in days = " + diff/(1000*60*60*24));

Cet exemple convertit deux objets de date date1 et date2 en millisecondes chacun reprsent sous forme de long. La diffrence est calcule en soustrayant time1 time2. La diffrence calcule en jours est ensuite imprime en ralisant lopration arithmtique ncessaire pour convertir la diffrence en millisecondes en une diffrence en jours. Il arrivera souvent que vous souhaitiez dterminer la dure qui spare deux dates, par exemple en calculant le nombre de jours restants avant lexpiration dun produit.

50

CHAPITRE 5 Dates et heures

Si vous connaissez la date dexpiration dun produit, vous pouvez calculer le nombre de jours avant expiration en calculant la diffrence entre la date dexpiration et la date courante. Voici un exemple de mthode pour raliser ce calcul : public static void daysTillExpired(Date expDate) { Date currentDate = new Date(); long expTime = expDate.getTime(); long currTime = currentDate.getTime(); long diff = expTime currTime; return diff/(1000*60*60*24); } Cette mthode prend une date dexpiration en entre et calcule le nombre de jours jusqu la date dexpiration. Cette valeur en jours est retourne par la mthode. Elle peut fournir un nombre ngatif si la date dexpiration est dpasse.

Comparer des dates


if (date1.equals(date2)) { System.out.println("dates are the same."); } else { if (date1.before(date2)) { System.out.println("date1 before date2"); } else { System.out.println("date1 after date2"); } }

Retrouver le jour de la semaine/ du mois/de lanne ou le numro de la semaine

51

Cet exemple utilise les mthodes equals() et before() de la classe Date. La mthode equals() retourne true si les valeurs de donnes sont les mmes. Sinon, elle retourne false. Les dates doivent tre les mmes la milliseconde prs pour que la mthode equals() retourne true. La mthode before() retourne true si la date sur laquelle elle est appele intervient avant la date qui lui est passe en paramtre. La classe Date possde galement une mthode after qui est utilise de manire analogue la mthode before() pour dterminer si la date partir de laquelle elle est appele intervient aprs la date passe en paramtre. La mthode compareTo() de la classe Date est aussi utile pour comparer deux dates. Elle prend un argument de det retourne une valeur dentier. Elle retourne 0 si la date partir de laquelle elle est appele quivaut celle passe en argument, une valeur ngative si elle lui est antrieure et une valeur positive si elle lui est ultrieure.

Retrouver le jour de la semaine/ du mois/de lanne ou le numro de la semaine


Calendar cal = Calendar.getInstance(); System.out.println("Day of week: " + cal.get(Calendar.DAY_OF_WEEK)); System.out.println("Month: " + cal.get(Calendar.MONTH)); System.out.println("Year: " + cal.get(Calendar.YEAR)); System.out.println("Week number: " + cal.get(Calendar.WEEK_OF_YEAR));

52

CHAPITRE 5 Dates et heures

Vous pouvez aisment dterminer des valeurs comme le jour de la semaine, le mois, lanne ou le numro de semaine avec la mthode get() de lobjet Calendar. Dans lexemple prcdent, nous obtenons un objet Calendar reprsentant la date et lheure courantes avec la mthode getInstance(). Nous imprimons ensuite le jour de la semaine, le mois, lanne puis la semaine de lanne en utilisant la mthode get() et en passant la constante Calendar approprie pour spcifier le champ rcuprer. Pour obtenir ces valeurs avec un objet Date, vous devez dabord convertir lobjet Date en un objet Calendar en utilisant la mthode setTime() dune instance Calendar et en passant lobjet Date convertir. La conversion entre les objets Date et Calendar a t prsente prcdemment dans ce chapitre.

Calculer une dure coule


long start = System.currentTimeMillis(); // Raliser une autre action long end = System.currentTimeMillis(); long elapsedTime = end start;

En calculant une dure coule, vous pouvez dterminer le temps requis pour raliser une action ou le temps de progression dun processus. Pour cela, vous devez utiliser la mthode System.currentTimeMillis() afin dobtenir lheure courante en millisecondes. Cette mthode doit tre utilise au dbut et la fin de la tche chronomtrer, afin de calculer la diffrence entre les deux mesures. La valeur retourne par la mthode System.currentTimeMillis() correspond au temps coul depuis le 1er janvier 1970, 00 h 00 s 00 ms, en millisecondes.

Calculer une dure coule

53

Le JDK 1.5 introduit une mthode nanoTime() dans la classe System, qui permet dobtenir une mesure plus prcise encore, la nanoseconde. Toutes les plates-formes ne prennent cependant pas en charge cette prcision : bien que la mthode nanoTime() soit disponible, il nest donc pas toujours possible de compter sur une mesure en nanosecondes. Ce niveau de prcision est souvent utile pour les tests, le profilage et lanalyse des performances.

6
Retrouver des motifs avec des expressions rgulires
Les expressions rgulires ont t introduites en Java la sortie du JDK 1.4. Les expressions rgulires spcifient des motifs pouvant tre retrouvs dans des squences de caractres. Elles sont particulirement utiles pour lanalyse des chanes et conomisent souvent au programmeur bien du temps et des efforts par rapport aux solutions qui ny font pas appel. Avant dtre ajoutes au Java, elles ont t utilises pendant des annes par les programmeurs UNIX. Les outils UNIX standard comme sed et awk les emploient notamment. Les expressions rgulires sont aussi couramment utilises dans le langage de programmation Perl. Leur ajout au JDK reprsente un intressant renforcement des capacits du Java. Dans ce chapitre, vous allez apprendre utiliser les fonctionnalits lies aux expressions rgulires du Java afin de retrouver et remplacer des portions de texte ou den dterminer la concordance au regard dun modle.

56

CHAPITRE 6 Retrouver des motifs avec des expressions rgulires

Grce ces acquis, vous pourrez dterminer les cas o lusage dun traitement par les expressions rgulires peut tre utile dans vos applications.

Les expressions rgulires en Java


Les classes Java Matcher et Pattern que vous utiliserez pour les oprations lies aux expressions rgulires sont contenues dans le paquetage java.util.regex. Elles permettent la fois de retrouver des squences de caractres et den dterminer la concordance daprs des motifs dexpression rgulire. Quelle diffrence faut-il faire entre "retrouver" et "dterminer la concordance" ? Lopration de recherche permet de retrouver des correspondances dans une chane. Lopration de dtermination de la concordance requiert que la chane entire soit une correspondance prcise de lexpression rgulire. Les tches pour lesquelles vous faisiez auparavant appel la classe StringTokenizer sont en gnral toutes dsignes pour tre simplifies laide dexpressions rgulires.
Info Si vous ne pouvez pas utiliser une version de Java contenant le paquetage des expressions rgulires (autrement dit, une version 1.4 ou ultrieure), il existe une bonne solution de remplacement avec le paquetage Jakarta RegExp dApache. Ce livre ne couvre pas le paquetage Jakarta, mais vous trouverez des informations et une documentation complte le concernant ladresse http://jakarta.apache.org/regexp.

Les expressions rgulires en Java

57

Le Tableau 6.1 prsente les caractres spciaux courants utiliss dans les expressions rgulires. Vous pourrez vous rfrer ce tableau en consultant les exemples du chapitre.
Tableau 6.1 : Tableau des expressions rgulires caractres spciaux couramment utiliss
Caractre spcifique Description

^ $ ? * + []
|

Dbut de la chane Fin de la chane 0 ou 1 fois (fait rfrence lexpression rgulire prcdente) 0 ou plusieurs fois (fait rfrence lexpression rgulire prcdente) 1 ou plusieurs fois (fait rfrence lexpression rgulire prcdente) Classe de caractres Oprateur union Nimporte quel caractre Un chiffre Caractre autre quun chiffre Caractre despace blanc (espace, tabulation, nouvelle ligne, saut de page, retour chariot) Caractre autre quespace blanc Caractre de mot [a-zA-Z_0-9] Caractre autre quun caractre de mot [^\w]

. \d \D \s \S \w \W

58

CHAPITRE 6 Retrouver des motifs avec des expressions rgulires

Dans le Tableau 6.1, les expressions rgulires chappes sont prsentes en tant prcdes par une unique barre oblique inverse. Notez cependant qu lintrieur des chanes Java, il convient dutiliser deux barres obliques inverses chaque fois. Le caractre de barre oblique inverse possde en effet une signification spciale en Java : la double barre oblique inverse chappe ds lors le caractre de barre oblique inverse et quivaut un unique caractre de barre oblique inverse. La JavaDoc de la classe Pattern propose une liste plus complte des caractres utiliss pour exprimer des expressions rgulires. Elle est disponible ladresse suivante : http://java.sun.com/j2se/1.5.0/docs/api/java/util/ regex/Pattern.html.

Retrouver une portion de texte laide dune expression rgulire


String pattern = "[TJ]im"; Pattern regPat = Pattern.compile(pattern); String text = "This is jim and Timothy."; Matcher matcher = regPat.matcher(text); if (matcher.find()) { String matchedText = matcher.group(); }

Cet exemple utilise les classes Pattern et Matcher. Pour commencer, nous utilisons la mthode compile() de la classe Pattern afin de compiler une chane de motif en un objet Pattern. Une fois que nous avons lobjet Pattern regPat, nous utilisons la mthode matcher() et passons la chane de texte en fonction de laquelle la correspondance

Retrouver une portion de texte laide dune expression rgulire

59

doit tre tablie. La mthode matcher() retourne une instance de la classe Matcher. Pour finir, nous appelons la mthode group() de la classe Matcher pour obtenir le texte correspondant. Le texte correspondant dans cet exemple est la chane "Tim". Notez que la chane "jim" nest pas une occurrence correspondante, car par dfaut, les expressions rgulires tiennent compte de la casse des caractres. Pour oprer une recherche en ignorant la casse, ce code doit tre lgrement modifi, comme ceci : String patt = "[TJ]im"; Pattern regPat = Pattern.compile(patt, Pattern.CASE_INSENSITIVE); String text = "This is jim and Timothy."; Matcher matcher = regPat.matcher(text); if (matcher.find()) { String matchedText = matcher.group(); } Le texte retourn est maintenant la chane de caractres "jim". La mise en correspondance ntant cette fois pas sensible la casse, la premire correspondance "jim" intervient avant la correspondance portant sur "Tim". Notez que la seule diffrence par rapport au prcdent exemple tient ce que nous avons ajout un paramtre supplmentaire la mthode compile() en crant notre objet Pattern. Cette fois-ci, nous passons le drapeau CASE_INSENSITIVE afin dindiquer que nous souhaitons que la correspondance soit tablie sans tenir compte de la casse. Lorsque ce drapeau nest pas inclus, la correspondance stablit par dfaut en tenant compte de la casse.

60

CHAPITRE 6 Retrouver des motifs avec des expressions rgulires

Si votre code doit sexcuter sous diffrents paramtres rgionaux, vous pouvez galement passer le drapeau de casse Unicode. La ligne de compilation ressemblera alors ceci : Pattern regPat = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); Comme vous le voyez, les diffrents drapeaux passs la mthode compile() sont spars les uns des autres par un signe OU logique. Les drapeaux Pattern doivent tre passs au moment o le Pattern est cr en utilisant la mthode compile(). Une fois que lobjet Pattern est cr, il est immuable, ce qui signifie quil ne peut plus tre chang. Dans les prcdents exemples, nous avons utilis la mthode find() de la classe Matcher pour retrouver la premire correspondance dans notre chane dentre. La mthode find() peut cependant tre appele de manire rptitive afin de retourner toutes les correspondances successives dans la chane dentre. La mthode find() retourne true chaque fois quune correspondance est trouve. Elle retourne false lorsquil ny a plus de correspondance. Si vous appelez find() de nouveau aprs quelle a retourn false, elle se rinitialise et retrouve la premire occurrence de nouveau. Il existe une autre mthode find() qui prend un paramtre int spcifiant un index partir duquel la recherche doit dmarrer. Pour le reste, cette mthode find() se comporte exactement comme la mthode find() sans paramtre. Dautres solutions sont possibles pour obtenir le rsultat de la correspondance. Nous avons utilis la mthode group() de la classe Matcher, mais il existe aussi des mthodes pratiques start() et end(). La mthode start()

Remplacer du texte mis en correspondance

61

retourne lindex au dbut de la prcdente correspondance. La mthode end() retourne lindex aprs le dernier caractre mis en correspondance.

Remplacer du texte mis en correspondance


String pattern = "[TJ]im"; Pattern regPat = Pattern.compile(pattern); String text = "This is jim and Tim."; Matcher matcher = regPat.matcher(text); String string2 = matcher.replaceAll("John");

Cet exemple montre comment remplacer le texte retrouv avec notre chane de motif par un texte de remplacement. La valeur de string2 la fin de cet exemple est la suivante : This is jim and John. Loccurrence de "jim" nest pas remplace, car la mise en correspondance des expressions rgulires tient par dfaut compte de la casse. Pour tablir une correspondance en ignorant la casse, rfrez-vous lexercice prcdent. Nous utilisons les classes Pattern et Matcher comme nous lavons fait lors de la mise en correspondance lmentaire de lexercice prcdent. Ltape nouvelle concerne ici notre appel la mthode replaceAll() de Matcher. Nous passons en paramtre le texte utiliser comme texte de remplacement. Celui-ci vient remplacer toutes les occurrences retrouves du motif. Cette technique est trs efficace pour remplacer des portions dune chane par une chane de remplacement.

62

CHAPITRE 6 Retrouver des motifs avec des expressions rgulires

Lautre technique utile pour le remplacement du texte consiste utiliser les mthodes appendReplacement() et appendTail() de la classe Matcher. Lusage combin de ces mthodes permet de remplacer des occurrences dune sous-chane lintrieur dune chane. Le code suivant prsente un exemple de cette technique : Pattern p = Pattern.compile("My"); Matcher m = p.matcher("My dad and My mom"); StringBuffer sb = new StringBuffer(); boolean found = m.find(); while(found) { m.appendReplacement(sb, "Our"); found = m.find(); } m.appendTail(sb); System.out.println(sb); La sortie de ce code produit limpression de la ligne suivante avec la mthode System.out.println() : Our dad and Our mom Dans cet exemple, nous crons un objet Pattern afin de retrouver les occurrences du texte "My". La mthode appendReplacement() crit les caractres de la squence dentre ("My dad and my mom") dans le tampon StringBuffer sb, jusquau dernier caractre avant la prcdente correspondance. Elle ajoute ensuite au StringBuffer la chane de remplacement passe en second paramtre. Pour finir, elle fixe la position de la chane courante au niveau de la fin de la dernire correspondance. Ce processus se rpte jusqu ce quil ny ait plus de correspondance. A ce moment-l, nous appelons la mthode appendTail() pour ajouter la portion restante de la squence dentre au StringBuffer.

Retrouver toutes les occurrences dun motif

63

Retrouver toutes les occurrences dun motif


String pattern = "\\st(\\w)*o(\\w)*"; Pattern regPat = Pattern.compile(pattern); String text = "The words are town tom ton toon house."; Matcher matcher = regPat.matcher(text); while (matcher.find()) { String matchedText = matcher.group(); System.out.println("match - " + matchedText); }

Dans les prcdents exemples du chapitre, nous navons trouv quune unique correspondance dun motif. Dans cet exemple, nous retrouvons toutes les occurrences dun motif de correspondance donn dans une chane. Le motif utilis est "\\st(\\w)*o(\\w)*". Cette expression rgulire retrouve tous les mots qui commencent par t et contiennent la lettre o. La sortie imprime par notre instruction System.out.println() est la suivante : town tom ton toon Dcomposons cette expression rgulire et voyons ce que chaque lment nous apporte : b \\s : caractre spcial dexpression rgulire correspondant un caractre despace blanc. b t : correspond la lettre t. b \\w* : caractre spcial dexpression rgulire correspondant zro, un ou plusieurs caractres de mot (qui ne sont pas des espaces blancs).

64

CHAPITRE 6 Retrouver des motifs avec des expressions rgulires

b o : correspond la lettre o. b \\w* : caractre spcial dexpression rgulire correspondant zro, un ou plusieurs caractres de mot (qui ne sont pas des espaces blancs). Cette expression rgulire ne correspond pas au premier mot de la chane, quand bien mme celui-ci commencerait par un t et contiendrait un o, car le premier lment de lexpression rgulire correspond un caractre despace blanc or gnralement, les chanes ne commencent pas par un espace blanc.

Imprimer des lignes contenant un motif


String pattern = "^a"; Pattern regPat = Pattern.compile(pattern); Matcher matcher = regPat.matcher(""); BufferedReader reader = new BufferedReader(new FileReader("file.txt")); String line; while ((line = reader.readLine()) != null) { matcher.reset(line); if (matcher.find()) { System.out.println(line); } }

Cet exemple montre comment effectuer une recherche dans un fichier afin de trouver toutes les lignes contenant un motif donn. Ici, nous utilisons la classe BufferedReader pour lire des lignes depuis un fichier texte. Nous tentons de mettre en correspondance chaque ligne avec notre motif en utilisant la mthode find() de la classe Matcher.

Retrouver des caractres de nouvelle ligne dans du texte

65

Cette mthode retourne true si le motif est trouv dans la ligne passe en paramtre. Nous imprimons toutes les lignes qui correspondent au motif donn. Notez que ce fragment de code peut lever des exceptions FileNotFoundException et IOException, quil convient de grer dans votre code. Dans cet exemple, lexpression rgulire correspond nimporte quelle ligne contenue dans notre fichier dentre qui commence par la lettre a minuscule. Le motif dexpression rgulire que nous utilisons se dcompose de la manire suivante : b ^ : caractre spcial dexpression rgulire correspondant au dbut dune chane. b a : correspond la lettre a.

Retrouver des caractres de nouvelle ligne dans du texte


String pattern = "\\d$"; String text = "This is line 1\nHere is line 2\nThis is line 3\n"; Pattern regPat = Pattern.compile(pattern, Pattern.MULTILINE); Matcher matcher = regPat.matcher(text); while (matcher.find()) { System.out.println(matcher.group()); }

Dans cet exemple, nous utilisons le drapeau Pattern.MULTILINE pour retrouver des caractres de nouvelle ligne dans une chane de texte. Par dfaut, les caractres dexpression rgulire ^ et $ ne correspondent quau dbut et la fin dune chane entire. Si une chane con-

66

CHAPITRE 6 Retrouver des motifs avec des expressions rgulires

tenait plusieurs lignes distingues par des caractres de nouvelle ligne, lexpression rgulire ^ ne correspondrait toujours quau dbut de la chane par dfaut. Si nous passons le drapeau Pattern.MULTILINE la mthode Pattern.compile() comme nous le faisons dans cet exemple, le caractre ^ correspond maintenant au premier caractre suivant un terminateur de ligne et le caractre $ au caractre prcdent un terminateur de ligne. Avec le drapeau Pattern.MULTILINE, le ^ correspond maintenant au dbut de chaque ligne dans une chane contenant plusieurs lignes spares par des caractres de nouvelle ligne. La sortie de cet exemple est la suivante : 1 2 3 Nous utilisons le motif "\\d$". Dans cette expression rgulire, le \\d correspond nimporte quel chiffre unique. En mode MULTILINE, le $ correspond au caractre intervenant juste avant un terminateur de ligne. Leffet intressant est que notre expression rgulire correspond tout caractre chiffre unique prsent la fin dune ligne. Nous obtenons donc la sortie prcdente.

7
Nombres
Le travail avec des nombres en Java est un domaine dans lequel tout bon programmeur se doit dtre aguerri, car presque tous les programmes ont affaire des nombres sous une forme ou une autre. Dans ce chapitre, nous utiliserons principalement les types numriques de base du Java, leurs objets encapsuleurs (wrappers) et la classe java.lang.Math. Le Tableau 7.1 prsente les types prdfinis du Java et liste leurs objets encapsuleurs disponibles. Notez que le type boolen ne possde pas de taille en bits parce quil ne peut contenir que deux valeurs discrtes, true ou false.
Tableau 7.1 : Types prdnis du Java
Type Taille en bits Objet encapsuleur

byte short int long

8 16 32 64

Byte Short Integer Long

68

CHAPITRE 7 Nombres

Tableau 7.1 : Types prdnis du Java (suite)


Type Taille en bits Objet encapsuleur

float double char boolean

32 64 16 --

Float Double Character Boolean

Les classes dobjet encapsuleur sont utiles lorsque vous souhaitez traiter un type de base comme un objet. Cette approche peut notamment tre utile si vous souhaitez dfinir une API manipulant uniquement des objets. En encapsulant vos nombres sous forme dobjets, vous pouvez aussi srialiser les types de base.

Vrier si une chane est un nombre valide


try { int result = Integer.parseInt(aString); } catch (NumberFormatException ex) { System.out.println("The string does not contain a valid number."); }

Dans cet exemple, nous utilisons la mthode statique parseInt() de la classe Integer pour tenter de convertir le paramtre chane en un entier. Si le paramtre chane ne peut pas tre converti en un entier valide, lexception

Comparer des nombres virgule flottante

69

NumberFormatException est leve. Si lexception NumberFormatException nest pas leve, on peut donc en conclure a contrario que la mthode parseInt() est parvenue par-

ser la chane en une valeur dentier. Il est aussi possible de dclarer la variable int en dehors du bloc try afin de pouvoir attribuer une valeur par dfaut la variable dans le bloc catch si lexception NumberFormatException est leve. Le code devient alors le suivant : int result = 0; try { result = Integer.parseInt(aString); } catch (NumberFormatException ex) { result = DEFAULT_VALUE; }

Comparer des nombres virgule ottante


Float a = new Float(3.0f); Float b = new Float(3.0f); if (a.equals(b)) { // Ils sont gaux }

Une prudence toute particulire est recommande lors de la comparaison des nombres virgule flottante en raison des erreurs darrondi. Au lieu de comparer les types Java de base virgule flottante float et double avec loprateur ==, il est prfrable de comparer leurs quivalents objet. La mthode equals() de Float et Double retourne true si et

70

CHAPITRE 7 Nombres

seulement si les deux valeurs sont exactement identiques au bit prs ou si elles correspondent toutes deux la valeur NaN. Cette valeur dsigne une valeur autre quun nombre (NaN pour not a number) qui nest pas un nombre valide. En pratique, lors de la comparaison des nombres virgule flottante, il nest pas toujours souhaitable deffectuer une comparaison exacte. Il est parfois plus judicieux de la fixer une plage diffrentielle acceptable, aussi appele tolrance. Les classes et les types Java ne possdent malheureusement pas de fonctionnalit prdfinie de ce type, mais vous pouvez assez aisment crer votre propre mthode equals() pour cela. Voici un fragment de code qui peut tre utilis pour crer une mthode de ce type : float f1 = 2.99f; float f2 = 3.00f; float tolerance = 0.05f; if (f1 == f2) System.out.println("they are equal"); else { if (Math.abs(f1-f2) < tolerance) { System.out.println("within tolerance"); } } Nous comparons dabord les nombres virgule flottante en utilisant loprateur ==. Sils sont gaux, nous imprimons un message correspondant. Sils ne le sont pas, nous vrifions si la valeur absolue de leur diffrence est infrieure la valeur de tolrance dsire. Cette technique permet de crer une mthode utile prenant en paramtre deux valeurs virgule flottante et une tolrance, et retournant un rsultat indiquant si les valeurs sont gales, la plage de tolrance prs.

Arrondir des nombres virgule flottante

71

Arrondir des nombres virgule ottante


// Arrondir une valeur double long longResult = Math.round(doubleValue); // Arrondir une valeur float int intResult = Math.round(floatValue);

Il convient dtre prudent si vous souhaitez convertir un nombre virgule flottante en un entier. Si vous vous contentez de transtyper le nombre virgule flottante en un int ou un long, la conversion en un int ou un long sopre en tronquant simplement la portion dcimale. Avec une valeur dcimale comme 20.99999, vous obtiendrez donc 20 aprs le transtypage en une valeur int ou long. La mthode approprie pour raliser une conversion de nombre virgule flottante en entier consiste utiliser la mthode Math.round(). Lexemple prcdent montre comment arrondir une valeur double et une valeur float. Si vous passez une valeur double la mthode Math.round(), le rsultat retourn est un long. Si vous passez une valeur float la mthode Math .round(), le rsultat retourn est un int. La mthode Math.round() arrondit la valeur vers le haut si la partie dcimale du nombre virgule flottante est 0,5 ou plus et vers le bas pour les nombres dont la partie dcimale est infrieure 0,5.

72

CHAPITRE 7 Nombres

Formater des nombres


double value = 1623542.765; NumberFormat numberFormatter; String formattedValue; numberFormatter = NumberFormat.getNumberInstance(); formattedValue = numberFormatter.format(value); System.out.format("%s%n", formattedValue);

Dans la plupart des applications, il est ncessaire dafficher des nombres. Le Java permet par chance le formatage des nombres, afin de leur donner lapparence dsire lorsque vous souhaitez les afficher dans votre application. Cet exemple gnre le nombre format suivant en sortie : 1 623 542,765 Dans cet exemple, nous utilisons la classe NumberFormat pour formater une valeur double en une reprsentation sous forme de chane spare par des espaces. La classe NumberFormat se trouve dans le paquetage java.text. Elle est aussi trs utile pour le code que vous devez diffuser dans plusieurs pays. La classe NumberFormat supporte le formatage de nombres et de devises et sait galement reprsenter des nombres et des devises laide de diffrents paramtres rgionaux. La classe NumberFormat peut aussi tre utilise pour formater des valeurs de pourcentage afficher. Voici un exemple utilisant la classe NumberFormat pour formater un pourcentage afficher : double percent = 0.80; NumberFormat percentFormatter; String formattedPercent; percentFormatter = NumberFormat.getPercentInstance();

Formater des nombres

73

formattedPercent = percentFormatter.format(percent); System.out.format("%s%n", formattedPercent);

La sortie de ce code est la suivante : 80% La classe NumberFormat possde galement une mthode parse() qui peut tre utilise pour parser des chanes contenant des nombres en un objet Number, partir duquel peut sobtenir un type numrique. Le JDK 1.5 a introduit la classe java.util.Formatter, un objet de formatage de porte gnrale permettant de formater un grand nombre de types. En plus des nombres, cette classe peut galement formater des dates et des heures. Elle est trs bien documente dans la documentation du JDK 1.5 ladresse suivante : http://java.sun.com/ j2se/1.5.0/docs/api/java/util/Formatter.html. Le JDK 1.5 ajoute aussi deux mthodes utilitaires la classe java.io.PrintStream pour un formatage ais des objets OutputStream : format() et printf(). Toutes deux prennent une chane de format et un nombre variable darguments Object en entre. Ces mthodes sont trs proches des mthodes de formatage des chanes classiques printf et scanf du C. Pour plus dinformations sur ces mthodes, rfrez-vous la documentation du JDK 1.5 ladresse http://java.sun.com/j2se/1.5.0/docs/api/ java/io/PrintStream.html. Dans lexemple suivant, nous allons voir comment formater des valeurs de devise afficher avec la classe NumberFormat.

74

CHAPITRE 7 Nombres

Formater des devises


double currency = 567123678.99; NumberFormat currencyFormatter; String formattedCurrency; currencyFormatter = NumberFormat.getCurrencyInstance(); formattedCurrency = currencyFormatter.format(currency); System.out.format("%s%n", formattedCurrency);

Comme pour lexemple prcdent concernant le formatage des nombres, nous utilisons ici la classe NumberFormat, mais afin de formater cette fois une valeur de devise. Nous utilisons la mthode getCurrencyInstance() de la classe NumberFormat pour obtenir une instance de formatage de devise de la classe. Avec cette instance, nous pouvons passer une valeur virgule flottante et rcuprer en retour une valeur de devise formate. La sortie de cet exemple produit la chane suivante : 567 123 678,99 En plus de placer des virgules aux emplacements appropris, le formateur de devises ajoute automatiquement le signe dollar aprs la chane (ou avant, selon les paramtres rgionaux).

Convertir un entier en nombre binaire, octal et hexadcimal


int intValue = 24; String binaryStr = Integer.toBinaryString(intValue); String octalStr = Integer.toOctalString(intValue); String hexStr = Integer.toHexString(intValue);

Gnrer des nombres alatoires

75

La classe Integer permet aisment de convertir une valeur dentier en un nombre binaire, octal ou hexadcimal. Les mthodes statiques concernes de la classe Integer sont les mthodes toBinaryString(), toOctalString() et toHexString(). Dans cet exemple, nous les utilisons chacune en passant dans chaque cas une valeur dentier et en obtenant en retour un objet String contenant respectivement lentier au format binaire, octal et hexadcimal.

Gnrer des nombres alatoires


Random rn = new Random(); int value = rn.nextInt(); double dvalue = rn.nextDouble();

La classe Random du paquetage java.util peut tre utilise pour gnrer des nombres alatoires. Par dfaut, elle utilise lheure courante du jour comme valeur de graine pour son gnrateur de nombres alatoires. Vous pouvez aussi dfinir vous-mme une valeur de graine en la passant comme paramtre au constructeur de Random. La mthode nextInt() produit un nombre alatoire entier 32 bits. Lautre moyen de gnrer des nombres alatoires consiste utiliser la mthode random() de la classe Math dans le paquetage java.lang. double value = Math.random(); Cette mthode retourne une valeur double avec un signe positif, suprieure ou gale 0,0 et infrieure 1,0. Pour gnrer une valeur comprise dans un intervalle spcifique, vous pouvez ajouter la limite infrieure au rsultat de Math.random() et multiplier par lintervalle.

76

CHAPITRE 7 Nombres

Le code suivant produit ainsi un nombre alatoire compris entre 5 et 20 : double value = (5+Math.random())*15; La classe Random et la mthode random() de la classe Math fournissent en fait un nombre pseudo-alatoire et non un vritable nombre alatoire, car ce nombre est gnr en utilisant une formule mathmatique et une valeur de graine dentre. Si lon connat la valeur de graine et le mcanisme interne de la classe Random, il est possible de prdire la valeur obtenue. Ces classes ne constituent donc gnralement pas une bonne solution pour les gnrateurs de nombres alatoires utiliser dans les applications fortement scurises. Dans la plupart des cas cependant, il sagit de gnrateurs de nombres alatoires parfaitement acceptables.

Calculer des fonctions trigonomtriques


// Calcul du cosinus double cosine = Math.cos(45); // Calcul du sinus double sine = Math.sin(45); // Calcul de la tangente double tangent = Math.tan(45);

La classe Math du paquetage java.lang contient des mthodes permettant de calculer aisment toutes les fonctions trigonomtriques. Cet exemple montre comment il est possible de rcuprer le cosinus, le sinus et la tangente dun angle donn. La classe Math possde galement des

Calculer un logarithme

77

mthodes pour calculer larc cosinus, larc sinus et larc tangente ainsi que le sinus, le cosinus et la tangente hyperboliques. Chacune de ces mthodes prend un unique paramtre de type double en entre et retourne un rsultat de type double.

Calculer un logarithme
double logValue = Math.log(125.5);

Cet exemple utilise la mthode log() de la classe java.lang.Math pour calculer le logarithme du paramtre pass. Nous passons une valeur de type double et la valeur de retour est galement un double. La mthode log() calcule le logarithme naturel de base e, o e correspond la valeur standard de 2,71828. Le JDK 1.5 a ajout une nouvelle mthode la classe Math afin de calculer directement un algorithme de base 10 : log10(). Cette mthode, analogue log(), prend en entre un paramtre double et retourne un double. Elle peut aisment tre utilise pour calculer un logarithme de base 10, comme ceci : double logBase10 = Math.log10(200);

8
Entre et sortie
Dans la plupart des cas, lentre et la sortie constituent le but ultime des applications. Les programmes seraient parfaitement inutiles sils ne pouvaient produire en sortie des rsultats ni rcuprer en entre des donnes traiter fournies par lutilisateur ou lordinateur. Dans ce chapitre, nous prsenterons quelques exemples de base pour les oprations dentre et de sortie. Les paquetages java.io et java.util abritent la plupart des classes utilises dans ce chapitre pour les tches dentre et de sortie. Nous verrons comment lire et crire des fichiers, travailler avec des archives ZIP, formater la sortie et travailler avec les flux de systme dexploitation standard. A mesure que vous lisez les exemples de ce chapitre, gardez lesprit que bon nombre des exercices peuvent lever des exceptions dans nimporte quel programme rel, telle lexception java.io.IOException. Dans les exemples, nous ninclurons pas le code de gestion des exceptions. Dans une application relle, il est cependant impratif quil soit prsent.

80

CHAPITRE 8 Entre et sortie

Lire du texte partir dune entre standard


BufferedReader inStream = new BufferedReader (new InputStreamReader(System.in)); String inLine = ""; while ( !(inLine.equalsIgnoreCase("quit"))) { System.out.print("prompt> "); inLine = inStream.readLine(); }

Dans un programme de console, il est courant de lire lentre standard qui provient le plus souvent de la ligne de commande. Cet exemple montre comment lire lentre dans une variable String Java. Le Java contient trois flux connects aux flux du systme dexploitation. Il sagit des flux standard dentre, de sortie et derreur. Ils sont respectivement dfinis en Java par System.in, System.out et System.err. Ils peuvent tre utiliss pour lire ou crire vers et depuis lentre et la sortie standard du systme dexploitation. Dans cet exemple, nous crons un BufferedReader afin de lire le flux System.in. Nous lisons avec ce lecteur les lignes de lentre standard en poursuivant jusqu ce que lutilisateur tape le mot "quit".

Ecrire vers une sortie standard


System.out.println("Hello, World!");
System.out est un PrintStream qui crit sa sortie vers la sortie standard (en gnral, la console). System.out est lun des trois flux dfini par le Java pour se connecter aux flux

Formater la sortie

81

de systme dexploitation standard. Les autres flux sont System.in et System.err, permettant de lire lentre standard et dcrire dans le flux derreur standard. Le flux System.out est probablement le flux de systme dexploitation standard le plus frquemment utilis. Il est mis contribution par la quasi-totalit des programmeurs pour le dbogage de leurs applications. Ce flux crit dans la console : il sagit ainsi dun outil pratique pour voir ce qui se passe un point particulier de lapplication. En gnral, les instructions System.out ne doivent cependant pas tre conserves dans les programmes aprs le dbogage initial, car elles peuvent en affecter les performances. A long terme, il est prfrable de rcolter les informations de dbogage dans votre application laide dun dispositif de journalisation comme celui que proposent java.util.logging ou le paquetage populaire Log4J dApache.

Formater la sortie
float hits=3; float ab=10; String formattedTxt = String.format("Batting average: %.3f", hits/ab);

Cet exemple utilise la mthode format() pour formater une chane de sortie qui imprime une moyenne la batte en baseball sous sa forme classique trois chiffres aprs la virgule. La moyenne est dfinie en divisant le nombre de coups russis par le nombre de "prsences la batte" (at-bats). Le spcificateur de format %.3f demande au formateur dimprimer la moyenne sous forme de nombre virgule flottante avec trois chiffres aprs la virgule.

82

CHAPITRE 8 Entre et sortie

Le JDK 1.5 a introduit la classe java.util.Formatter qui peut tre utilise pour simplifier le formatage du texte. La classe Formatter opre la manire de la fonction printf du langage C et offre une prise en charge de la justification et de lalignement pour la mise en page, des formats courants pour les donnes numriques, les chanes et les dates et heures, ainsi quune sortie spcifique en fonction des paramtres rgionaux. Voici un exemple dutilisation directe de la classe Formatter : StringBuffer buffer = new StringBuffer(); Formatter formatter = new Formatter(buffer, Locale.FRANCE); formatter.format("Value of PI: %6.4f", Math.PI); System.out.println(buffer.toString()); Ce code produit la sortie suivante : Value of PI: 3,1416 Dans cet exemple, nous crons une instance Formatter et lutilisons pour formater la valeur mathmatique standard du nombre pi. Celle-ci contient un nombre infini de chiffres aprs la virgule, mais il est gnralement prfrable den restreindre le nombre au moment de limprimer. Dans cet exemple, nous avons utilis le spcificateur de format %6.4f. La valeur 6 indique que la sortie pour ce nombre ne doit pas dpasser 6 caractres de longueur en comptant la virgule. La valeur 4 indique que la prcision de la valeur dcimale doit tre de 4 chiffres aprs la virgule. La valeur imprime atteint donc 6 caractres de longueur et possde 4 chiffres aprs la virgule : 3,1416. En plus dutiliser directement la classe Formatter, vous pouvez utiliser les mthodes format() et printf() des flux System.out et System.err. Voici par exemple comment

Formater la sortie

83

imprimer lheure locale en utilisant la mthode format() du flux System.out : System.out.format("Local time: %tT", Calendar.getInstance()); Cette mthode imprime lheure locale, comme ceci : Local time: 16:25:14 La classe String contient galement une mthode statique format() qui peut tre utilise pour formater directement des chanes. Nous pouvons par exemple utiliser cette mthode statique pour formater aisment une chane de date comme ceci : Calendar c = new GregorianCalendar(1999, Calendar.JANUARY, 6); String s = String.format("Timmys Birthday: %1$tB %1$te, %1$tY", c); Ce code cre la valeur String formate suivante : Timmys Birthday: Janvier 6, 1999 Toutes les mthodes qui produisent une sortie formate dont nous avons trait prennent une chane de format et une liste darguments en paramtres. La chane de format est un objet String qui peut contenir du texte et un ou plusieurs spcificateurs de format. Pour notre exemple de formatage prcdent, la chane de format serait "Timmy's Birthday: %1$tm %1$te,%1$tY", les lments %1$tm, %1$te et $1$tY tant les spcificateurs de format. Le reste de la chane correspond du texte statique. Ces spcificateurs de format indiquent comment les arguments doivent tre traits et lendroit de la chane o ils doivent tre placs.

84

CHAPITRE 8 Entre et sortie

Pour faire rfrence notre exemple de nouveau, la liste darguments correspond simplement lobjet Calendar c. Dans cet exemple, nous navons quun seul argument, mais la liste peut en contenir plusieurs. Tous les paramtres passs aux mthodes de formatage aprs la chane de format sont considrs comme des arguments. Les spcificateurs de format possdent le format suivant :
%[index_argument$][drapeaux][largeur][.prcision] conversion
index_argument fait rfrence un argument dans la liste des arguments passe la mthode de formatage. La liste est indexe en commenant 1. Pour faire rfrence au premier argument, vous devez donc utiliser 1$.

Llment drapeaux dsigne un ensemble de caractres qui modifient le format de sortie. Lensemble de drapeaux valides dpend du type de conversion. Llment largeur est un entier dcimal positif indiquant le nombre minimal de caractres crire dans la sortie. Llment prcision est un entier dcimal positif normalement utilis pour restreindre le nombre de caractres. Le comportement spcifique dpend du type de conversion. Llment conversion est un caractre indiquant comment largument doit tre format. Lensemble des conversions valides pour un argument donn dpend du type de donnes de largument. Tous les lments spcificateurs sont facultatifs lexception du caractre de conversion. Le Tableau 8.1 prsente une liste des caractres de conversion valides. Pour plus dinformations sur les conversions de date et dheure, rfrez-vous au JavaDoc de la classe Formatter ladresse suivante : http://java.sun.com/ j2se/1.5.0/docs/api/.

Formater la sortie

85

Tableau 8.1 : Codes de format de Formatter


Code Description

Si largument arg est null, le rsultat est false. Si arg est un boolean ou un Boolean, le rsultat est la chane retourne par String.valueOf(). Sans cela, le rsultat est true. Si largument arg est null, le rsultat est "null". Sans cela, le rsultat est obtenu en invoquant Integer.toHexString(arg.hashCode()). Si largument arg est null, le rsultat est "null". Si arg implmente Formattable, arg.formatTo est invoque. Sans cela, le rsultat est obtenu en invoquant arg.toString(). Le rsultat est un caractre Unicode. Le rsultat est format sous forme dentier dcimal. Le rsultat est format sous forme dentier octal. Le rsultat est format sous forme dentier hexadcimal. Le rsultat est format comme un nombre dcimal. Le rsultat est format sous forme de nombre dcimal en notation scientifique informatise. Le rsultat est format en utilisant une notation scientifique informatise ou le format dcimal, selon la prcision et la valeur aprs larrondi. Le rsultat est format sous forme de nombre hexadcimal virgule flottante avec une mantisse et un exposant. Prfixe pour les caractres de conversion de date et dheure. Le rsultat est le sparateur de ligne spcifique la plate-forme. Le rsultat est un % littral.

c d o x f e g

t n %

86

CHAPITRE 8 Entre et sortie

Pour obtenir une liste complte des codes de format disponibles, rfrez-vous la documentation JavaDoc de la classe Formatter qui peut tre consulte ladresse http://java.sun.com/j2se/1.5.0/docs/api/java/util/ Formatter.html.

Ouvrir un chier par son nom


// Ouvrir un fichier en lecture BufferedReader is = new BufferedReader(new FileReader("file.txt")); // Ouvrir un fichier en criture BufferedWriter out = new BufferedWriter(new FileWriter("afile.txt"));

Cet exemple montre comment crer un BufferedReader pour lire lentre dun fichier spcifi par un nom de fichier (ici, file.txt) et comment crer un BufferedWriter pour crire du texte vers un fichier de sortie spcifi par son nom (afile.txt). Il est trs facile douvrir un fichier dsign par son nom en Java. La plupart des classes de flux dentre et de sortie ou de lecteur possdent une option permettant de spcifier le fichier par nom dans le flux ou le constructeur du lecteur.

Lire un fichier dans un tableau doctets

87

Lire un chier dans un tableau doctets


File file = new File(fileName); InputStream is = new FileInputStream(file); long length = file.length(); byte[] bytes = new byte[(int)length]; int offset = 0; int numRead = 0; while ((offset < bytes.length) && ((numRead=is.read(bytes, offset, bytes.length-offset))>= 0)) { offset += numRead; } is.close();

Cet exemple lit le fichier spcifi par fileName dans le tableau doctets bytes. Notez que la mthode file.length() retourne la longueur du fichier en octets sous forme de valeur long, mais nous devons utiliser une valeur int pour initialiser le tableau doctets. Nous transtypons donc dabord la valeur long en une valeur int. Dans un vritable programme, il conviendrait pralablement de sassurer que la valeur de longueur tient effectivement dans un type int avant de la transtyper laveuglette. Avec la mthode read() du InputStream, nous continuons lire les octets du fichier jusqu ce que le tableau doctets soit rempli ou quil ny ait plus doctets lire dans le fichier.

88

CHAPITRE 8 Entre et sortie

Lire des donnes binaires


InputStream is = new FileInputStream(fileName); int offset = 0; int bytesRead = is.read(bytes, offset, bytes.length-offset);

La mthode read() permet de lire des donnes binaires depuis un fichier dans un tableau doctets. Dans cet exemple, nous lisons le flux dentre is dans le tableau doctets bytes. Le tableau bytes est ici suppos avoir t prcdemment initialis sous forme de tableau doctets et la variable fileName correspondre au nom dun fichier valide. La variable offset pointe lemplacement du tableau doctets partir duquel lcriture des donnes doit tre commence. Elle est utile lorsque vous vous trouvez dans une boucle, que vous lisez les donnes dun fichier et que vous ne souhaitez pas craser les donnes prcdemment stockes dans le tableau doctets. A chaque passage dans la boucle, vous pouvez mettre jour ce dcalage, comme nous lavons vu dans lexemple prcdent, "Lire un fichier dans un tableau doctets". Voici la portion de code concerne : while ( (offset < bytes.length) && ( (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) ) { offset += numRead; } Dans cet exemple de code, nous crivons des donnes depuis le flux dente is dans le tableau bytes. Nous poursuivons la lecture depuis le fichier jusqu ce que nous ayons rempli le tableau bytes ou quil ny ait plus de donnes lire dans le fichier.

Atteindre une position dans un fichier

89

Atteindre une position dans un chier


File file = new File("somefile.bin"); RandomAccessFile raf = new RandomAccessFile(file, "rw"); raf.seek(file.length());

La mthode seek() de la classe RandomAccessFile permet datteindre nimporte quelle position dsire dans un fichier. Dans cet exemple, nous crons dabord un objet File, qui est ensuite utilis pour crer une instance RandomAccessFile. Avec linstance RandomAccessFile (raf), nous recherchons la fin du fichier en passant la valeur file.length() en paramtre la mthode seek(). Aprs avoir utilis la mthode seek() pour trouver la position dsire dans le fichier, nous pouvons ensuite utiliser les mthodes read() ou write() de la classe RandomAccessFile pour lire ou crire des donnes partir de cette position exacte.

Lire une archive JAR ou ZIP


// Lire un fichier ZIP ZipFile file = new ZipFile(filename); Enumeration entries = file.entries(); while (entries.hasMoreElements()) { ZipEntry entry = (ZipEntry)entries.nextElement(); if (entry.isDirectory()) { // Traiter le rpertoire } else { // Traiter le fichier } } file.close();

90

CHAPITRE 8 Entre et sortie

Le Java offre un support intgr pour la lecture et lcriture de fichiers darchive ZIP. Les fichiers ZAR ntant autres que des fichiers ZIP possdant un contenu prcis, les classes et les mthodes des fichiers ZIP peuvent galement tre utilises pour les lire. Les classes ZIP sont contenues dans le paquetage java.util.zip qui fait partie du JDK standard. Dans cet exemple, nous crons dabord un objet ZipFile en passant le nom de fichier dun fichier ZIP existant au constructeur de la classe ZipFile. Nous obtenons ensuite lensemble des entres du fichier ZIP dans un type dnumration en appelant la mthode entries() de lobjet ZipFile. Une fois en possession des entres de fichier ZIP sous forme dnumration, nous pouvons parcourir au pas pas les entres et instancier un objet ZipEntry pour chaque entre. Avec lobjet ZipEntry, nous pouvons dterminer si lentre particulire qui est traite est un rpertoire ou un fichier et la traiter en fonction.

Crer une archive ZIP


// Ecrire un fichier ZIP ZipOutputStream out = new ZipOutputStream(new FileoutputStream(zipFileName)); FileInputStream in = new FileInputStream(fileToZip1); out.putNextEntry(new ZipEntry(fileToZip1)); int len; byte[] buf = new byte[1024]; while ((len = in.read(buf)) > 0) { out.write(buf,0,len); } out.closeEntry(); in.close(); out.close();

Crer une archive ZIP

91

Dans lexemple prcdent, nous avons vu comment lire dans un fichier ZIP. Cette fois, nous crons un fichier ZIP. Pour cela, nous commenons par construire un ZipOutputStream en passant son constructeur un objet FileOutputStream pointant vers le fichier que nous souhaitons compresser sous forme de fichier ZIP. Ensuite, nous crons un FileInputStream pour le fichier que nous souhaitons ajouter notre archive ZIP. Nous utilisons la mthode putNextEntry() du ZipOutputStream pour ajouter le fichier larchive. La mthode putNextEntry() prend un objet ZipEntry en entre : nous devons donc construire le ZipEntry partir du nom du fichier que nous ajoutons notre archive. Dans une boucle while, nous lisons ensuite notre fichier en utilisant le FileInputStream et lcrivons dans le ZipOutputStream. Une fois cela fait, nous fermons lentre en utilisant la mthode closeEntry() du ZipOutputStream, puis fermons chacun de nos flux ouverts. Dans cet exemple, nous navons ajout quun seul fichier notre archive ZIP, mais ce code peut aisment tre tendu afin dajouter autant de fichiers que ncessaire larchive. La classe ZipOutputStream accepte aussi bien les entres compresses que les entres non compresses.

9
Travailler avec des rpertoires et des chiers
Lune des tches courantes dans la plupart des applications Java consiste travailler avec le systme de fichiers et notamment ses rpertoires et ses fichiers. Ce chapitre prsente un certain nombre dexemples destins vous aider travailler avec des fichiers et des rpertoires en Java. La principale classe que nous utiliserons pour ces exemples est la classe java.io.File. Elle permet de lister, crer, renommer et supprimer des fichiers, mais encore de travailler avec des rpertoires. Bon nombre des exemples de ce chapitre peuvent lever une exception SecurityException. En Java, le systme de fichiers est protg par le gestionnaire de scurit. Pour certaines applications, il peut falloir en utiliser une implmentation personnalise. Parmi les applications Java, les applets sont les plus restreintes en ce qui concerne laccs

94

CHAPITRE 9 Travailler avec des rpertoires et des fichiers

aux fichiers et aux rpertoires sur lordinateur local de lutilisateur. En tirant parti du gestionnaire de scurit et du framework de stratgie de scurit li vous pouvez contrler prcisment laccs aux fichiers et aux rpertoires. Pour plus dinformations sur les options de scurit disponibles en Java, consultez la documentation de scurit disponible (en anglais) sur le site Web Java officiel ladresse http://java.sun.com/javase/technologies/ security.jsp. Pour plus dinformations sur le gestionnaire de scurit, consultez le didacticiel suivant (en anglais) propos par Sun : http://java.sun.com/docs/books/tutorial/essential/ system/securityIntro.html.

Crer un chier
File f = new File("myfile.txt"); boolean result = f.createNewFile();

Cet exemple utilise la mthode createNewFile() pour crer un nouveau fichier portant le nom spcifi en paramtre (ici, myfile.txt) en construisant lobjet File. La mthode createNewFile() retourne la valeur boolenne true si le fichier a bien t cr et false si le nom de fichier spcifi existe dj. La classe File propose une autre mthode statique pour crer un fichier temporaire : createTempFile(). Lexemple suivant montre comment lutiliser pour crer un fichier temporaire : File tmp = File.createTempFile("temp", "txt", "/temp");

Renommer un fichier ou un rpertoire

95

Les paramtres que nous passons la mthode createTempFile() sont le prfixe du fichier temporaire, son suffixe et son rpertoire. Il existe aussi une autre version de cette mthode qui ne prend que deux paramtres et utilise le rpertoire temporaire par dfaut. Le fichier spcifi doit dj exister pour que lune ou lautre forme des mthodes createTempFile() puisse fonctionner. Si vous utilisez des fichiers temporaires, la mthode deleteOnExit() de la classe File peut aussi vous intresser. Elle doit tre appele sur un objet File qui reprsente un fichier temporaire. Lappel de la mthode deleteOnExit() requiert que le fichier soit automatiquement supprim lorsque la machine virtuelle Java se ferme.

Renommer un chier ou un rpertoire


File f = new File("myfile.txt"); File newFile = new File("newname.txt"); boolean result = f.renameTo(newFile);

Dans cet exemple, nous renommons le fichier myfile.txt en lappelant newname.txt. Pour cela, nous devons crer deux objets File. Le premier est construit avec le nom courant du fichier. Ensuite, nous crons un nouvel objet File en utilisant le nom de remplacement que nous souhaitons donner au fichier. Nous appelons la mthode renameTo() de lobjet File dorigine et lui passons lobjet File spcifiant le nouveau nom de fichier. La mthode renameTo() retourne la valeur boolenne true si lopration de modification du nom russit et false sinon, quelle que soit la raison.

96

CHAPITRE 9 Travailler avec des rpertoires et des fichiers

Cette technique peut galement tre utilise pour renommer un rpertoire. Le code est alors exactement le mme, la diffrence que nous passons cette fois les noms de rpertoire aux constructeurs de lobjet File au lieu des noms de fichier. Voici comment procder : File f = new File("directoryA"); File newDirectory = new File("newDirectory"); boolean result = f.renameTo(newDirectory); Rappelez-vous que le nouveau nom de fichier ou de rpertoire doit tre spcifi dans un objet File pass la mthode renameTo(). Lune des erreurs courantes consiste tenter de passer un objet String contenant le nouveau nom de fichier ou de rpertoire la mthode renameTo(). Une erreur de compilation est gnre si un objet String est pass la mthode renameTo().

Supprimer un chier ou un rpertoire


File f = new File("somefile.txt"); boolean result = f.delete();

La classe File permet aisment de supprimer un fichier. Dans cet exemple, nous crons dabord un objet File en spcifiant le nom du fichier supprimer. Ensuite, nous appelons la mthode delete() de lobjet File. Elle retourne la valeur boolenne true si le fichier a bien t supprim et false sinon. La mthode delete() peut aussi tre utilise pour supprimer un rpertoire. Dans ce cas, vous devez crer lobjet

Modifier des attributs de fichier

97

File en spcifiant le nom du rpertoire au lieu dun nom

de fichier, comme ceci :


File directory = new File("files/images"); directory.delete();

Le rpertoire nest supprim que sil est vide. Sil ne lest pas, la mthode delete() retourne la valeur boolenne false. Si le fichier ou le rpertoire que vous essayez de supprimer nexiste pas, delete() retourne aussi false, sans lever dexception. La classe File propose une autre mthode utile lie la suppression des fichiers et des rpertoires : deleteOnExit(). Lorsquelle est appele, le fichier ou le rpertoire reprsent par lobjet File sont automatiquement supprims lorsque la machine virtuelle Java se ferme.

Modier des attributs de chier


File f = new File("somefile.txt"); boolean result = f.setReadOnly(); long time = (new Date()).getTime(); result = f.setLastModified(time);

Lobjet File permet aisment de modifier lhorodatage de dernire modification et ltat de lecture/criture dun fichier. Pour raliser ces tches, vous devez utiliser les mthodes setReadOnly() et setLastModified() de la classe File. La mthode setReadOnly() positionne en lecture seule le fichier sur lequel elle est appele. La mthode setLastModified() prend un unique paramtre en entre spcifiant une date en millisecondes et positionne lhorodatage de dernire modification du fichier cette date.

98

CHAPITRE 9 Travailler avec des rpertoires et des fichiers

La valeur temporelle passe est mesure en millisecondes coules depuis lpoque UNIX (1er janvier 1970, 00 h 00 m 00 s, GMT). Ces deux mthodes retournent la valeur boolenne true uniquement si lopration russit. Si lopration choue, elles retournent false.

Obtenir la taille dun chier


File file = new File("infilename"); long length = file.length();

Dans cet exemple, nous retrouvons la taille dun fichier en utilisant la mthode length() de lobjet File. Cette mthode retourne la taille du fichier en octets. Si le fichier nexiste pas, elle retourne 0. Cette mthode est souvent utile avant de lire un fichier sous forme de tableau doctets. Grce la mthode length(), vous pouvez dterminer la longueur du fichier afin de connatre la taille requise pour que le tableau doctets contienne la totalit du fichier. Le code suivant est ainsi souvent utilis pour lire un fichier dans un tableau doctets : File myFile = new File("myfile.bin"); InputStream is = new FileInputStream(myFile); // Obtenir la taille du fichier long length = myFile.length(); if (length > Integer.MAX_VALUE) { // Le fichier est trop grand } byte[] bytes = new byte[(int)length]; int offset = 0; int numRead = 0;

Dterminer si un fichier ou un rpertoire existe

99

while (offset < bytes.length && (numRead=is.read(bytes, offset, bytes.lengthoffset)) >= 0) { offset += numRead; } is.close();

Dterminer si un chier ou un rpertoire existe


boolean exists = (new File("filename")).exists(); if (exists) { // Le fichier ou le rpertoire existe } else { // Le fichier ou le rpertoire nexiste pas }

Cet exemple utilise la mthode exists() de lobjet File pour dterminer si le fichier ou le rpertoire reprsent par cet objet existe. Elle retourne true si le fichier ou le rpertoire existe et false sinon.

Dplacer un chier ou un rpertoire


File file = new File( "filename "); File dir = new File( "directoryname "); boolean success = file.renameTo(new File(dir, file.getName())); if (!success) { // Le fichier na pas pu tre dplac }

100 CHAPITRE 9 Travailler avec des rpertoires et des fichiers

La mthode renameTo() de la classe File permet de dplacer un fichier ou un rpertoire dans un autre rpertoire. Dans cet exemple, nous crons un objet File afin de reprsenter le fichier ou le rpertoire dplacer. Nous crons un autre objet File reprsentant le rpertoire de destination dans lequel nous souhaitons dplacer le fichier ou le rpertoire, puis appelons la mthode renameTo() du fichier dplac en lui passant un unique paramtre dobjet File. Lobjet File pass en paramtre est construit en utilisant le rpertoire de destination et le nom de fichier dorigine. Si lopration de dplacement russit, la mthode renameTo() retourne la valeur boolenne true. En cas dchec, elle retourne false. Lorsque vous utilisez la mthode renameTo(), gardez lesprit que bien des aspects de ce comportement dpendent de la plate-forme dexcution. Certains sont signals dans le JavaDoc pour cette mthode, et notamment les suivants : b Lopration renameTo peut ne pas tre capable de dplacer un fichier dun systme de fichiers un autre. b Lopration renameTo peut ne pas tre atomique. Autrement dit, limplmentation de lopration renameTo peut se dcomposer en plusieurs tapes au niveau du systme dexploitation : cette particularit peut poser problme en cas dincident, comme lors dune coupure de courant survenant entre les tapes. b Lopration renameTo peut chouer si un fichier possdant le nom du chemin abstrait de destination existe dj. Lorsque vous utilisez cette mthode, vrifiez toujours la valeur de retour afin de vous assurer que lopration a russi.

Obtenir un chemin de nom de fichier absolu partir dun chemin relatif

101

Obtenir un chemin de nom de chier absolu partir dun chemin relatif


File file = new File( "somefile.txt "); File absPath = file.getAbsoluteFile();

Cet exemple retrouve le chemin absolu dun fichier dont le chemin relatif est spcifi. Le chemin absolu dfinit le chemin complet du fichier en commenant partir du rpertoire racine du systme de fichiers, comme ceci : c:\project\book\somefile.txt. Le nom de fichier relatif spcifie le nom et le chemin du fichier par rapport au rpertoire courant, comme somefile.txt si le rpertoire courant est c:\project\book. Dans bien des cas, le nom de chemin relatif nest constitu que du nom de fichier. La mthode getAbsoluteFile() de la classe File retourne une objet File reprsentant le nom de fichier absolu pour le fichier reprsent par lobjet File sur lequel elle est appele. Une autre mthode similaire, getAbsolutePath(), retourne le chemin absolu sous forme de String et non dobjet File. Le code suivant prsente cette mthode : File file = new File( "filename.txt "); String absPath = file.getAbsolutePath(); Dans cet exemple, absPath contient la chane "c:\project\ book\somefile.txt".

102 CHAPITRE 9 Travailler avec des rpertoires et des fichiers

Dterminer si un chemin de nom de chier correspond un chier ou un rpertoire


File testPath boolean isDir if (isDir) { // testPath } else { // testPath } = new File( "directoryName "); = testPath.isDirectory(); est un rpertoire est un fichier

Cet exemple dtermine si lobjet File dsign reprsente un fichier ou un rpertoire. La mthode isDirectory() de la classe File retourne true si lobjet File sur lequel elle est appele reprsente un rpertoire et false sil reprsente un fichier. Elle est utile lorsque vous souhaitez parcourir lensemble des fichiers et sous-rpertoires dun rpertoire donn. Par exemple, vous pourriez souhaiter crire une mthode qui liste tous les fichiers dun rpertoire et parcoure de manire rcurrente chacun de ses sous-rpertoires. La mthode isDirectory() peut tre utilise lorsque vous parcourez la liste des lments contenus dans chaque rpertoire afin de dterminer sil sagit dun fichier ou dun rpertoire. Voici un exemple de ce type de mthode qui utilise la mthode isDirectory() : static void listAllFiles(File dir) { String[] files = dir.list(); for (int i = 0; i < files.length; i++) { File f = new File(dir, files[i]);

Lister un rpertoire

103

if (f.isDirectory()) { listAllFiles(f); } else { System.out.println(f.getAbsolutePath()); } } }

Si vous appelez cette mthode et lui passez un objet File reprsentant un rpertoire, elle imprime les chemins complets de tous les fichiers contenus dans le rpertoire et dans lensemble de ses sous-rpertoires. La classe File contient aussi une mthode isFile() qui retourne true si lobjet File sur lequel elle est appele reprsente un fichier et false sinon.

Lister un rpertoire
File directory = new File("users/tim"); String[] result = directory.list();

La classe File peut aussi tre utilise pour lister le contenu dun rpertoire. Cet exemple utilise la mthode list() de la classe File pour obtenir un tableau dobjets String contenant tous les fichiers et sous-rpertoires contenus dans le rpertoire spcifi par lobjet File. Si le rpertoire nexiste pas, la mthode retourne null. Les chanes retournes sont des noms de fichiers et des noms de rpertoire simples et non des chemins complets. Lordre des rsultats nest pas garanti.

104 CHAPITRE 9 Travailler avec des rpertoires et des fichiers

La mthode list() possde une autre implmentation qui prend un paramtre java.io.FilenameFilter et permet de filtrer les fichiers et rpertoires retourns dans les rsultats de la mthode. En voici un exemple : File directory = new File("users/tim"); FilenameFilter fileFilter = new HTMLFileFilter(); String[] result = directory.list(fileFilter); Voici maintenant limplmentation correspondante de la classe HTMLFileFilter : class HTMLFileFilter extends FilenameFilter { public boolean accept(File f) { return f.isDirectory() || f.getName() .toLowerCase() .endsWith(".html")); } public String getDescription() } return "/html files"; }
FilenameFilter est une interface dfinissant une mthode nomme accept(). Celle-ci prend deux paramtres : un objet File et un objet String. Lobjet File spcifie le rpertoire dans lequel le fichier a t trouv et lobjet String spcifie le nom du fichier. La mthode accept() retourne true si le fichier doit tre inclus dans la liste et false sinon. Dans cet exemple, nous avons cr un filtre qui amne la mthode list() ninclure que les fichiers qui se terminent par lextension .html.

Si le filtre pass est null, la mthode se comporte comme la prcdente mthode list() sans paramtre. En plus des mthodes list(), la classe File propose deux versions dune mthode appele listFiles().

Lister un rpertoire

105

listFiles() retourne un tableau dobjets File au lieu dun tableau de chanes. Lexemple utilise sa variante sans paramtre : File directory = new File("users/tim"); File[] result = directory.listFiles();

Les objets File rsultants contiennent des chemins relatifs ou absolus selon lobjet File depuis lequel la mthode listFiles() a t appele. Si lobjet File de rpertoire dans cet exemple contient un chemin absolu, le rsultat contient des chemins absolus. Si lobjet File de rpertoire contient un chemin relatif, les rsultats sont des chemins relatifs. Lautre version de listFiles() prend un paramtre FileFilter, de manire analogue lexemple prsent pour la mthode list(). En voici un exemple :
File directory = new File("users/tim"); FileFilter fileFilter = new HTMLFileFilter(); String[] result = directory.listFiles(fileFilter);

Voici maintenant limplmentation correspondante de la classe HTMLFileFilter : class HTMLFileFilter extends FileFilter { public boolean accept(File f) { return f.isDirectory() || f.getName().toLowerCase().endsWith(".html"); } public String getDescription() { return ".html files"; } }

106 CHAPITRE 9 Travailler avec des rpertoires et des fichiers

FileFilter est une interface dfinissant deux mthodes, accept() et getDescription(). A la diffrence de la mthode accept() de FilenameFilter, la mthode accept() de FileFilter ne prend quun paramtre, un objet File. Lobjet File spcifie un fichier ou un rpertoire. La mthode accept() retourne true si le fichier ou le rpertoire doivent tre inclus dans la liste et false

sinon. Dans cet exemple, nous avons cr un filtre qui amne la mthode list() ninclure que les rpertoires ou les fichiers qui se terminent par lextension .html.

Crer un nouveau rpertoire


boolean success = (new File("users/tim")).mkdir();

Cet exemple utilise la mthode mkdir() de la classe File pour crer un nouveau rpertoire. mkdir() retourne true si le rpertoire a pu tre cr et false sinon. Elle ne cre de rpertoire que si tous les rpertoires parents spcifis existent dj. Ici, il est donc ncessaire que le rpertoire users existe dj pour que mkdir() parvienne crer le rpertoire users/tim. La mthode mkdirs() de la classe File est une mthode similaire qui permet de crer un arbre de rpertoires complet en gnrant tous les rpertoires parents sils nexistent pas. En voici un exemple : boolean success = (new File("/users/tim/Web")).mkdirs( ); A lexcution de cette instruction, la mthode mkdirs() crera tous les rpertoires (users, tim, Web) qui nexistent pas.

10
Clients rseau
La plupart des applications crites aujourdhui requirent diffrents types de fonctionnalits rseau. Les applications Java entirement autonomes se font de plus en plus rares. Ce chapitre sur les clients rseau a donc toutes les chances dtre utile la plupart des dveloppeurs Java qui conoivent des applications aujourdhui. Les programmes rseau impliquent une communication entre un client et un serveur. En gnral, le client est lapplication qui transmet une demande de contenu ou de services et le serveur une application rseau qui sert ce contenu et ces services de nombreux clients. Dans ce chapitre, nous nous concentrerons spcifiquement sur le client. Le Chapitre 11, "Serveurs rseau" traite des exemples lis au serveur. A lexception dun exemple concernant la lecture dune page Web via HTTP, les exemples de ce chapitre oprent tous au niveau de la programmation avec les sockets. Les sockets sont une implmentation rseau de bas niveau. Dans la plupart des cas, vous chercherez utiliser un protocole situ au niveau juste suprieur celui de la couche des sockets, comme le HTTP, le SMTP ou le POP.

108 CHAPITRE 10 Clients rseau

Dautres API Java ou tierces permettent de travailler avec ces protocoles rseau de plus haut niveau. Le paquetage java.net fournit les fonctionnalits de communication rseau ct client que nous utiliserons dans ce chapitre. La plate-forme J2EE (que nous nabordons pas dans ce livre) propose de nombreux services rseau supplmentaires dont un support complet du dveloppement Web Java ct serveur. Parmi les technologies rseau incluses dans la plate-forme J2EE, on peut citer les servlets, les EJB et le JMS.

Contacter un serveur
String serverName = "www.timothyfisher.com"; Socket sock = new Socket(serverName, 80);

Dans cet exemple, nous nous connectons un serveur via TCP/IP laide de la classe Java Socket. Lors de la construction de linstance sock, une connexion de socket est opre au serveur spcifi par serverName ici, www.timothyfisher.com, sur le port 80. A chaque fois quun Socket est cr, vous devez veiller fermer le socket lorsque vous avez termin en appelant la mthode close() sur linstance Socket avec laquelle vous travaillez. Le Java prend en charge dautres mthodes de connexion au serveur dont nous ne traiterons pas en dtail ici. Par exemple, vous pouvez utiliser la classe URL pour ouvrir une URL et la lire. Pour plus de dtails sur lutilisation de la classe URL, consultez lexemple "Lire une page Web via HTTP" de ce chapitre.

Retrouver des adresses IP et des noms de domaine

109

Retrouver des adresses IP et des noms de domaine


// Trouver ladresse IP dun domaine String hostName = www.timothyfisher.com"; String ip = InetAddress.getByName(hostName).getHostAddress(); // Trouver le nom de domaine de ladresse IP String ipAddress = "66.43.127.5"; String hostName = InetAddres.getByName(ipAddress).getHostName();

Dans cet exemple, nous rcuprons le nom dhte correspondant une adresse IP connue, puis nous rcuprons ladresse IP correspondant un nom dhte distant. Pour ces deux tches, nous faisons appel la classe InetAddress. Nous utilisons la mthode statique getByName() de la classe InetAddress pour crer une instance InetAddress. Nous pouvons passer une adresse IP ou un nom dhte la mthode getByName() pour crer linstance InetAddress. Une fois linstance InetAddress cre, nous pouvons appeler la mthode getHostAddress() pour retourner ladresse IP sous forme de String. Si nous connaissons dj ladresse IP, nous pouvons appeler la mthode getHostName() pour retourner le nom dhte sous forme de String. Si le nom dhte ne peut pas tre rsolu, la mthode getHostName() retourne ladresse IP.

110 CHAPITRE 10 Clients rseau

Grer les erreurs rseau


try { // Connexion lhte rseau // Ralisation des E/S rseau } catch (UnknownHostException ex) { System.err.println("Unknown host."); } catch (NoRouteToHostException ex) { System.err.println("Unreachable host."); } catch (ConnectException ex) { System.err.println("Connect refused."); } catch (IOException ex) { System.err.println(ex.getMessage()); }

Cet exemple prsente les exceptions que vous devez tenter de capturer lorsque vous ralisez des oprations rseau. La premire exception que nous essayons de capturer est lexception UnknownHostException. Il sagit dune sous-classe dIOException. Elle est leve afin dindiquer que ladresse IP dun hte ne peut tre dtermine.
NoRouteToHostException et ConnectException sont des sous-classes de SocketException. NoRouteToHostException

signale quune erreur sest produite lors de la tentative de connexion un socket une adresse et un port distants. En gnral, lhte distant ne peut pas tre atteint en raison dun problme li un pare-feu ou un routeur interpos. Lexception ConnectException est leve si une connexion lhte distant est refuse. IOException est une exception de porte plus gnrale qui peut galement tre leve partir dappels rseau.

Lire du texte

111

Les exemples de ce chapitre et du suivant nincluent pas de mcanisme de gestion des erreurs. Il convient cependant de capturer ces exceptions dans vos applications Java qui utilisent des fonctionnalits rseau.

Lire du texte
BufferedReader in = new BufferedReader (new InputStreamReader(socket.getInputStream())); String text = in.readLine();

Cet exemple suppose que vous avez prcdemment cr un socket au serveur partir duquel vous souhaitez lire du texte. Pour plus dinformations sur la cration dune instance de socket, consultez lexemple "Contacter un serveur" de ce chapitre. Une fois linstance socket obtenue, nous appelons la mthode getInputStream() pour obtenir une rfrence au flux dentre du socket. Avec cette rfrence, nous crons un InputStreamReader et lutilisons pour instancier un BufferedReader. Nous lisons enfin le texte sur le rseau avec la mthode readLine() du BufferedReader. Cet usage du BufferedReader permet deffectuer une lecture efficace des caractres, des tableaux et des lignes. Si vous cherchez simplement lire une trs petite quantit de donnes, vous pouvez cependant aussi procder directement depuis InputStreamReader, sans utiliser de BufferedReader. Voici comment lire des donnes dans un tableau de caractres en nutilisant quun InputStreamReader : InputStreamReader in = new InputStreamReader(socket.getInputStream())); String text = in.read(charArray, offset, length);

112 CHAPITRE 10 Clients rseau

Dans cet exemple, les donnes sont lues depuis le flux dentre dans le tableau de caractres spcifi par charArray. Les caractres sont placs dans le tableau en commenant une position spcifie par le paramtre de dcalage offset, et le nombre maximal de caractres lus est spcifi par le paramtre length.

Ecrire du texte
PrintWriter out = new PrintWriter(socket.getOutputStream(), true); out.print(msg); out.flush();

Cet exemple requiert que vous ayez prcdemment cr un socket au serveur destination duquel vous souhaitez crire du texte. Pour plus de dtails sur la cration de linstance de socket, consultez lexemple "Contacter un serveur" de ce chapitre. Une fois linstance de socket obtenue, nous appelons la mthode getOutputStream() pour obtenir une rfrence au flux de sortie du socket. Lorsque la rfrence est acquise, nous instancions un PrintWriter afin dcrire du texte sur le rseau vers le serveur avec lequel nous sommes connects. Le second paramtre que nous passons au constructeur PrintWriter dans cet exemple dfinit loption de purge automatique. La valeur true amne les mthodes println(), printf() et format() vider automatiquement le tampon de sortie. Dans notre exemple, nous utilisons la mthode print(). Nous devons donc la faire suivre par un appel la mthode flush() pour forcer lenvoi des donnes sur le rseau.

Lire des donnes binaires

113

Lire des donnes binaires


DataInputStream in = new DataInputStream(socket.getInputStream()); in.readUnsignedByte();

Cet exemple montre comment lire des donnes binaires sur un rseau. Il requiert que vous ayez prcdemment cr un socket au serveur partir duquel vous souhaitez lire du texte. Pour plus de dtails sur la cration de linstance de socket, consultez lexemple "Contacter un serveur" de ce chapitre. Dans cet exemple, nous appelons la mthode getInputStream() de linstance de socket afin dobtenir une rfrence au flux dentre du socket. En passant le flux dentre en paramtre, nous instancions un DataInputStream, que nous pouvons utiliser pour lire des donnes binaires sur le rseau. Nous utilisons la mthode readUnsignedByte() pour lire un unique octet non sign sur le rseau. Si le volume de donnes que vous lisez est important, il est prfrable dencapsuler le flux dentre du socket dans une instance BufferedInputStream, comme ceci : DataInputStream in = new DataInputStream(new BufferedInputStream(socket.getInputStream())); Ici, au lieu de passer directement le flux dentre du socket au constructeur DataInputStream, nous crons dabord une instance BufferedInputStream et la passons au constructeur DataInputStream. Dans cet exemple, nous avons utilis la mthode readUnsignedByte(), mais DataInputStream possde bien dautres mthodes pour lire des donnes dans nimporte quel type de donnes Java primitif, dont les suivantes : read(),

114 CHAPITRE 10 Clients rseau

readBoolean(), readByte(), readChar(), readDouble(), readFloat(), readInt(), readLong(), readShort(), readUnsignedByte() et readUnsignedShort(). Consultez le JavaDoc pour

plus de dtails sur lutilisation de ces mthodes et dautres mthodes de la classe DataInputStream : http://java.sun .com/j2se/1.5.0/docs/api/java/io/DataInputStream .html.

Ecrire des donnes binaires


DataOutputStream out = new DataOutputStream(socket.getOutputStream()); out.write(byteArray, 0, 10);

Dans lexemple "Ecrire du texte" vu prcdemment, nous avons montr comment crire des donnes texte sur un rseau. Cet exemple montre comment crire des donnes binaires sur le rseau. Il requiert que vous ayez prcdemment cr un socket au serveur destination duquel vous souhaitez crire du texte. Pour plus de dtails sur la cration de linstance de socket, consultez lexemple "Contacter un serveur" de ce chapitre. Dans cet exemple, nous appelons la mthode getOutputStream() de linstance de socket pour obtenir une rfrence au flux de sortie du socket. Nous instancions ensuite un DataOutputStream, que nous pouvons utiliser pour crire des donnes binaires sur le rseau. Nous utilisons la mthode write() pour crire un tableau doctets sur le rseau. La mthode write() prend trois paramtres. Le premier est un byte[] servant rcuprer les octets partir desquels crire. Le second dfinit un dcalage dans le tableau doctets servant dterminer la position partir de laquelle lcriture doit tre effectue. Le troisime

Lire des donnes srialises

115

spcifie le nombre doctets crire. Dans cet exemple, nous crivons des octets du tableau byteArray en commenant la position 0 et en crivant 10 octets. Si le volume des donnes que vous crivez est important, il devient plus efficace dencapsuler le flux de sortie du socket dans une instance BufferedOutputStream, comme ceci : DataOutputStream out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); Au lieu de passer directement le flux de sortie de socket au constructeur DataOutputStream, nous crons dabord une instance BufferedOutputStream et la passons au constructeur DataOutputStream. Dans cet exemple, nous avons utilis la mthode write(), mais DataOutputStream possde bien dautres mthodes pour crire des donnes depuis nimporte quel type de donnes Java primitif, dont les suivantes : write(), writeBoolean(), writeByte(), writeBytes(), writeChar(), writeChars(), writeDouble(), writeFloat(), writeInt(), writeLong() et writeShort(). Pour plus de dtails sur lutilisation de ces mthodes de la classe DataOutputStream, consultez le JavaDoc ladresse http://java.sun.com/j2se/1.5.0/docs/api/ java/io/DataOutputStream.html.

Lire des donnes srialises


ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); Object o = in.readObject();

Le Java permet de srialiser les instances dobjet et de les crire dans un fichier ou sur un rseau. Cet exemple montre comment lire un objet srialis depuis un socket rseau.

116 CHAPITRE 10 Clients rseau

Il requiert que vous ayez prcdemment cr un socket au serveur avec lequel vous souhaitez communiquer. Pour plus de dtails sur la cration de linstance de socket, consultez lexemple "Contacter un serveur" de ce chapitre. Dans cet exemple, nous appelons la mthode getInputStream() de linstance de socket afin dobtenir une rfrence au flux dentre du socket. Avec cette rfrence, nous pouvons instancier un ObjectInputStream. La classe ObjectInputStream est utilise pour dsrialiser des donnes et des objets primitifs prcdemment crits en utilisant un ObjectOutputStream. Nous utilisons la mthode readObject() de lobjet ObjectInputStream pour lire un objet depuis le flux. Lobjet peut ensuite tre transtyp en son type attendu. Par exemple, pour lire un objet Date depuis le flux, nous utiliserions la ligne suivante : Date aDate = (Date)in.readObject(); Tous les champs de donnes qui ne sont pas transitoires et statiques retrouvent la valeur qui tait la leur lorsque lobjet a t srialis. Seuls les objets qui supportent linterface java.io.Serializable ou java.io.Externalizable peuvent tre lus depuis des flux. Lors de limplmentation dune classe srialisable, il est vivement recommand de dclarer un membre de donnes serialVersionUID. Ce champ fournit un numro de version qui est utilis lors de la dsrialisation pour vrifier que lmetteur et le rcepteur dun objet srialis ont charg pour cet objet des classes compatibles en termes de srialisation. Si vous ne dclarez pas explicitement ce champ, un serialVersionUID par dfaut est automatiquement calcul. Ce serialVersionUID par dfaut tient finement compte des particularits de dtail de la classe. Si vous apportez des modifications mineures une classe et que vous souhaitiez conserver le mme

Ecrire des donnes srialises

117

numro de version en considrant que cette implmentation reste compatible avec la version courante, vous devez dclarer votre propre serialVersionUID.

Ecrire des donnes srialises


ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()); out.writeObject(myObject);

Le Java permet de srialiser les instances dobjet et de les crire dans un fichier ou sur un rseau. Cet exemple montre comment lire un objet srialis depuis un socket rseau. Il requiert que vous ayez prcdemment cr un socket au serveur avec lequel vous souhaitez communiquer. Pour plus de dtails sur la cration de linstance de socket, consultez lexemple "Contacter un serveur" de ce chapitre. Dans cet exemple, nous appelons la mthode getOutputStream() de linstance de socket pour obtenir une rfrence au flux de sortie du socket. Avec cette rfrence, nous instancions un ObjectOutputStream. La classe ObjectOutputStream est utilise pour srialiser des donnes et des objets primitifs. Nous utilisons la mthode writeObject() de ObjectOutputStream pour crire un objet dans le flux. Tous les champs de donnes qui ne sont pas transitoires et statiques sont prservs dans la srialisation et restaurs lorsque lobjet est dsrialis. Seuls les objets qui supportent linterface java.io.Serializable peuvent tre crits dans des flux.

118 CHAPITRE 10 Clients rseau

Lire une page Web via HTTP


URL url = new URL("http://www.timothyfisher.com"); HttpURLConnection http = new HttpURLConnection(url); InputStream in = http.getInputStream();

Cet exemple prsente un autre moyen de lire des donnes depuis le rseau avec une programmation de plus haut niveau que le niveau socket auquel se cantonnaient les prcdents exemples. Le Java peut communiquer avec une URL sur le protocole HTTP grce la classe HttpURLConnection. Ici, nous instancions un objet URL en passant une chane dURL valide au constructeur URL. Ensuite, nous instancions un HttpURLConnection en passant linstance url au constructeur HttpURLConnection. La mthode getInputStream() est appele pour obtenir un flux dentre afin de lire les donnes depuis la connexion dURL. A laide du flux dentre, nous pouvons ensuite lire le contenu de la page Web. Il est aussi possible de lire le contenu dune URL en utilisant directement la classe URL, comme ceci : URL url = new URL("http://www.timothyfisher.com"); url.getContent(); La mthode getContent() retourne un Object. Celui-ci peut tre un InputStream ou un objet contenant les donnes. Par exemple, la mthode getContent() peut retourner un objet String stockant le contenu dune URL. La mthode getContent() que nous venons dutiliser est en fait un raccourci du code suivant : url.openConnection.getContent();

Lire une page Web via HTTP

119

La mthode openConnection() de la classe URL retourne un objet URLConnection. Il sagit de lobjet dans lequel la mthode getContent() se trouve en fait implmente.
HttpURLConnection fournit des mthodes spcifiques au

HTTP qui ne sont pas disponibles dans les classes plus gnrales URL ou URLConnection. Par exemple, on peut utiliser la mthode getResponseCode() pour obtenir le code dtat dun message de rponse HTTP. Le HTTP dfinit galement un protocole pour rediriger les requtes vers un autre serveur. La classe HttpURLConnection contient des mthodes qui comprennent cette fonctionnalit galement. Par exemple, si vous souhaitez oprer une requte un serveur et suivre toutes les redirections quil retourne, vous pouvez utiliser le code suivant pour dfinir cette option : URL url = new URL("http://www.timothyfisher.com"); HttpURLConnection http = new HttpURLConnection(url); http.setFollowRedircts(true); Loption est en fait positionne true par dfaut. Le cas pratique le plus utile consistera donc au contraire positionner loption de suivi des redirections false lorsque vous ne souhaitiez pas automatiquement tre redirig vers un autre serveur que celui sur lequel votre requte portait initialement. Cette mesure restrictive pourrait notamment tre envisage avec certaines applications de scurit, lorsque vous ne faites confiance qu certains serveurs spcifis. Les pages Web qui contiennent des donnes sensibles sont gnralement protges par un protocole de scurit appel SSL (Secure Sockets Layer). Les pages protges par SSL sont dsignes par le prfixe "https" dans la chane dURL, au lieu du prfixe "http" habituel.

120 CHAPITRE 10 Clients rseau

Le JDK standard inclut une implmentation du SSL dans le cadre de JSSE (Java Secure Socket Extension). Pour rcuprer une page protge par SSL, vous devez utiliser la classe HttpsURLConnection au lieu de HttpURLConnection. HttpsURLConnection gre tous les dtails du protocole SSL, en toute transparence. Pour plus dinformations sur lutilisation du SSL et les autres fonctionnalits de scurit fournies par JSSE, consultez le guide de rfrence JSSE propos par Sun ladresse : http://java.sun.com/j2se/ 1.5.0/docs/guide/security/jsse/JSSERefGuide.html.

11
Serveurs rseau
En pratique, il y a bien plus de chances que vous criviez du code de client rseau que du code de serveur rseau. Toutefois, bon nombre dapplications intgrent la fois des fonctionnalits client et des fonctionnalits serveur. Le Java propose par chance un excellent support pour les deux. Le paquetage java.net fournit les fonctionnalits de communication rseau ct serveur que nous utiliserons dans ce chapitre. La plate-forme J2EE (que nous nabordons pas dans ce livre) propose de nombreux services rseau supplmentaires dont un support complet du dveloppement Web Java ct serveur. Parmi les technologies rseau incluses dans la plate-forme J2EE, on peut citer les servlets, les EJB et le JMS.

122 CHAPITRE 11 Serveurs rseau

Crer un serveur et accepter une requte


public static final short PORT = 9988; ServerSocket server = new ServerSocket(PORT); while ((clientSock = server.accept( )) != null) { // Traiter la demande du client }

Cet exemple utilise une instance ServerSocket pour crer un serveur coutant sur le port 9988. Nous passons le port sur lequel nous souhaitons que le serveur coute au constructeur du ServerSocket. Une fois le socket serveur cr, nous appelons la mthode accept() pour attendre une connexion client. La mthode accept() bloque lexcution jusqu ce quune connexion avec un client soit opre. Lorsquune connexion est tablie, une nouvelle instance Socket est retourne. Si un gestionnaire de scurit est utilis, sa mthode checkAccept() est appele avec clientSock.getInetAddress().getHostAddress() et clientSock.getPort() en arguments, afin de sassurer que lopration est autorise. Cette vrification peut lever une exception SecurityException. Les exemples de ce chapitre utilisent tous la classe ServerSocket. Elle est utilise par le serveur pour attendre et tablir les connexions client. Lexemple prcdent la montr : lorsque vous commencez par crer une classe ServerSocket, vous devez spcifier un port couter pour les requtes entrantes. La classe ServerSocket elle-mme nest pas utilise pour la communication avec le client, mais uniquement pour tablir une connexion

Retourner une rponse

123

avec lui. Lorsque ServerSocket accepte une connexion client, une instance Socket standard est retourne. Cest cette instance qui est utilise pour communiquer avec le client. Pour plus dinformations sur la manire dcrire votre code lorsque vous vous attendrez devoir grer de nombreuses requtes clientes simultanes, consultez lexemple "Grer plusieurs clients" de ce chapitre.

Retourner une rponse


Socket clientSock = serverSocket.accept(); DataOutputStream out = new DataOutputStream(clientSock.getOutputStream()); out.writeInt(someValue); out.close();

Cet exemple montre comment retourner une rponse du serveur au client. La mthode accept() de linstance ServerSocket retourne une instance Socket lorsquune connexion est tablie avec un client. Nous obtenons ensuite le flux de sortie de ce socket en appelant la mthode getOutputStream() de cet objet. Nous utilisons le flux de sortie pour instancier un DataOutputStream et appelons la mthode writeInt() de ce dernier pour crire une valeur entire envoye sous forme de donnes binaires au client. Pour finir, nous fermons le socket en utilisant la mthode close() du Socket. Cet exemple utilise la mthode write(), mais DataOutputStream possde bien dautres mthodes pour crire des donnes depuis nimporte quel type de donnes Java primitif, et notamment les suivantes : write(), writeBoolean(), writeByte(), writeBytes(), writeChar(), writeChars(), writeDouble(), writeFloat(), writeInt(), writeLong() et writeShort().

124 CHAPITRE 11 Serveurs rseau

Pour plus dinformations sur lutilisation de ces mthodes et des autres mthodes de la classe DataOutputStream, consultez la JavaDoc ladresse http://java.sun.com/j2se/ 1.5.0/docs/api/java/io/DataOutputStream.html. Si vous souhaitez crire des donnes texte au client, utilisez le code suivant : Socket clientSock = serverSocket.accept(); PrintWriter out = new PrintWriter(new OutputStreamWriter(clientSock.getOutputStream()), true); out.println("Hello World"); out.close(); Au lieu de crer un DataOutputStream, nous crons cette fois un OutputStreamWriter et un PrintWriter. La mthode print() du PrintWriter permet dcrire une chane de texte destination du client. Le second paramtre pass au constructeur PrintWriter dfinit loption de purge automatique. La valeur true amne les mthodes println(), printf() et format() vider automatiquement le tampon de sortie. Comme notre exemple utilise la mthode println(), il nest pas ncessaire dappeler explicitement la mthode flush(). Enfin comme toujours, lorsque nous avons fini dutiliser le PrintWriter, nous appelons la mthode close() pour fermer le flux.

Retourner un objet
Socket clientSock = serverSocket.accept(); ObjectOutputStream os = new ObjectOutputStream(clientSock.getOutputStream( )); // Retourner un objet os.writeObject(new Date()); os.close();

Retourner un objet

125

Cet exemple retourne un objet srialis au client. Nous obtenons une instance Socket que retourne la mthode accept() du ServerSocket une fois quune connexion un client est tablie. Nous crons alors une instance ObjectOutputStream et passons le flux de sortie obtenu depuis le socket client. ObjectOutputStream est utilise pour crire des types de donnes primitifs et des graphes dobjets Java vers un OutputStream. Dans cet exemple, nous crivons un objet Date dans le flux de sortie puis fermons ce flux. La mthode writeObject() srialise lobjet pass en paramtre. Dans cet exemple, il sagit dun objet Date. Tous les champs de donnes qui ne sont pas transitoires et dynamiques sont prservs dans la srialisation et restaurs lorsque lobjet est dsrialis. Seuls les objets qui supportent linterface java.io.Serializable peuvent tre srialiss. Le projet open source XStream de codehaus.org propose une alternative intressante aux classes ObjectOutputStream et ObjectInputStream. XStream fournit des implmentations de ObjectInputStream et ObjectOutputStream qui permettent aux flux dobjets dtre srialiss ou dsrialiss en XML. La classe ObjectInputStream standard utilise un format binaire pour les donnes srialises. La sortie srialise des classes XStream fournit pour sa part les classes srialises dans un format XML facile lire. Pour plus dinformations sur XStream et pour tlcharger ce projet, rendez-vous ladresse http://xstream.codehaus.org/ index.html.

126 CHAPITRE 11 Serveurs rseau

Grer plusieurs clients


while (true) { Socket clientSock = socket.accept(); new Handler(clientSock).start(); }

Pour grer plusieurs clients, il suffit de crer un thread pour chaque requte entrante traiter. Dans cet exemple, nous crons un nouveau thread pour grer la connexion cliente entrante immdiatement aprs avoir accept la connexion. Ce procd permet de librer notre thread dcouteur de serveur qui peut retourner couter les connexions clientes suivantes. Dans cet exemple, nous nous trouvons lintrieur dune boucle while infinie : ds quun thread est engendr pour grer une requte entrante, le serveur retourne immdiatement attendre la requte suivante. La classe Handler que nous utilisons pour dmarrer le thread doit tre une sousclasse de la classe Thread ou doit implmenter linterface Runnable. Le code utilis dans lexemple est correct si la classe Handler est une sous-classe de la classe Thread. Si la classe Handler implmente au contraire linterface Runnable, le code de dmarrage du thread devient alors le suivant : Thread thd = new Thread(new Handler(clientSock)); thd.start(); Voici lexemple dune classe Handler simple qui tend la classe Thread : class Handler extends Thread { Socket sock;
Handler(Socket socket) { this.sock = socket; }

Grer plusieurs clients

127

public void run() { DataInputStream in = new DataInputStream(sock.getInputStream()); PrintStream out = new PrintStream(sock.getOutputStream(), true); // Gestion de la requte cliente sock.close(); } }

Cette classe peut tre utilise pour grer des requtes clientes entrantes. Limplmentation concrte de la gestion des requtes spcifiques dans le code est volontairement masque ici, aux fins de lillustration. Lorsque la mthode start() de cette classe est appele, comme cest le cas dans notre exemple prcdent, la mthode run() dfinie ici est excute. start() est implmente dans la classe de base Thread : nous navons pas la redfinir dans notre implmentation de Handler. Lors de la cration dune solution multithreade de ce type, il peut aussi tre intressant de crer un systme de pooling des threads. Dans ce cas, vous crerez un pool de threads au dmarrage de lapplication au lieu dengendrer un nouveau thread pour chaque requte entrante. Le pool de threads contient un nombre fixe de threads pouvant excuter des tches. Ce systme vite que lapplication ne cre un nombre excessif de threads qui pourraient grever les performances systme. Un trs bon article (en anglais) concernant le pooling des threads peut tre consult ladresse http://www.informit.com/articles/article.asp?p=30483&seqNum=3&rl=1. Pour plus dinformations sur lutilisation des threads, consultez le Chapitre 15, "Utiliser des threads".

128 CHAPITRE 11 Serveurs rseau

Servir du contenu HTTP


Socket client = serverSocket.accept(); BufferedReader in = new BufferedReader (new InputStreamReader(client.getInputStream())); // Avant de servir une rponse, on lit habituellement // lentre cliente et on traite la requte. PrintWriter out = new PrintWriter(client.getOutputStream()); out.println("HTTP/1.1 200"); out.println("Content-Type: text/html"); String html = "<html><head><title>Test Response" + "</title></head><body>Just a test</body></html>"; out.println("Content-length: " + html.length()); out.println(html); out.flush(); out.close();

Cet exemple montre comment servir du contenu HTML trs simple via HTTP. Pour commencer, nous acceptons une connexion avec un client, crons un BufferedReader pour lire la requte cliente et crons un PrintWriter que nous utilisons pour retransmettre le HTML via HTTP au client. Les donnes que nous crivons vers le PrintWriter constituent le minimum ncessaire pour crer un message de rponse HTTP valide. Notre rponse est compose de trois champs den-tte HTTP et de nos donnes HTML. Nous commenons notre rponse en spcifiant la version HTTP et un code de rponse dans la ligne suivante : out.println("HTTP/1.1 200"); Nous indiquons le HTTP version 1.1 et le code de rponse 200. Ce code signale que la requte a russi. A la ligne suivante, nous signalons que le type de contenu retourn est du HTML. Dautres types de contenu peuvent tre retourns pour un message de rponse HTTP valide.

Servir du contenu HTTP

129

Par exemple, la ligne suivante spcifie que la rponse correspond du texte brut et non du code HTML : out.println("Content-Type: text/plain"); Ensuite, nous crivons len-tte Content-length. Celui-ci spcifie la longueur du contenu retourn, sans tenir compte des champs den-tte. Aprs cela, nous crivons le message HTML retourner. Pour finir, nous purgeons le flux BufferedReader et le fermons avec les mthodes flush() et close().
Info Cette technique est utile pour les besoins simples en matire de service HTTP, mais il nest pas recommand dcrire de toutes pices un serveur HTTP complet en Java. Un excellent serveur HTTP, gratuit et open source, est disponible dans le cadre du projet Jakarta dApache : le serveur Tomcat. Pour plus dinformations sur Tomcat et pour en tlcharger les fichiers, accdez http://jakarta.apache.org/tomcat/. Tomcat sert du contenu sur HTTP mais fournit galement un conteneur de servlets pour grer les servlets Java et les JSP.

12
Envoyer et recevoir des e-mails
Le-mail est utilis dans de nombreuses applications. Il est fort probable qu un stade ou un autre de vos projets de dveloppement, vous soyez conduit prendre en charge des courriers lectroniques dans lune de vos applications Java. Le Java facilite lintgration des fonctionnalits de messagerie lectronique vos applications Java grce lAPI JavaMail. Cette API est une extension du Java que vous devez tlcharger sparment. Elle ne fait pas partie du paquetage JDK standard propos en tlchargement. Les classes utiles qui constituent lAPI JavaMail se trouvent dans le paquetage javax.mail. LAPI JavaMail actuelle requiert le JDK 1.4 ou une version ultrieure. Les versions antrieures du JDK ncessitent des versions galement antrieures de lAPI JavaMail.

132 CHAPITRE 12 Envoyer et recevoir des e-mails

Ce chapitre traite de lenvoi et de la rception de-mails partir dune application Java. Lintgration des capacits de messagerie lectronique votre application Java constitue un excellent ajout dans de nombreuses applications. En pratique, ces fonctionnalits peuvent tre utiles pour envoyer des alertes par e-mail, transmettre automatiquement des journaux et des rapports et plus gnralement, communiquer avec les utilisateurs.

Vue densemble de lAPI JavaMail


JavaMail fournit des fonctionnalits pour envoyer et recevoir des e-mails. Des fournisseurs de service sajoutent comme composants additionnels lAPI JavaMail pour offrir des implmentations de diffrents protocoles de messagerie. Limplmentation Sun inclut des fournisseurs de services pour IMAP, POP3 et SMTP. JavaMail fait galement partie de Java Enterprise dans J2EE. Pour tlcharger lextension JavaMail, rendez-vous ladresse http://java.sun.com/products/javamail/downloads/ index.html. Pour utiliser lAPI JavaMail, vous devez galement tlcharger et installer lextension JAF (JavaBeans Activation Framework) depuis http://java.sun.com/products/javabeans/ jaf/downloads/index.html. En plus des exemples traits dans ce chapitre, vous pouvez trouver des informations dtailles compltes sur lutilisation de lAPI JavaMail grce au lien JavaMail de rseau des dveloppeurs Sun (en anglais) : http://java.sun.com/ products/javamail/index.jsp.

Envoyer des e-mails

133

Envoyer des e-mails


Properties props = new Properties( ); props.put("mail.smtp.host", "mail.yourhost.com"); Session session = Session.getDefaultInstance(props, null); Message msg = new MimeMessage(session); msg.setFrom(new InternetAddress("tim@timothyfisher.com")); InternetAddress toAddress = new InternetAddress("kerry@timothyfisher.com");

Cet exemple envoie un message lectronique en texte brut laide dun serveur SMTP. Six tapes de base doivent tre imprativement suivies lorsque vous souhaitez envoyer un e-mail avec lAPI JavaMail : 1. Vous devez crer un objet java.util.Properties, que vous utiliserez pour passer des informations concernant le serveur de messagerie. 2. Vous devez placer le nom dhte du serveur de messagerie SMTP dans lobjet Properties, ainsi que toutes les autres proprits dfinir. 3. Vous devez crer des objets Session et Message. 4. Vous devez dfinir les adresses e-mail du destinataire et de lexpditeur du message ainsi que son sujet dans lobjet Message. 5. Vous devez dfinir le texte du message dans lobjet Message. 6. Vous devez appeler la mthode Transport.send() pour envoyer le message. Lexemple prcdent suit chacune de ces tapes pour crer et envoyer un message lectronique. Notez que les adresses de provenance (From) et de destination (To) sont cres sous forme dobjets InternetAddress. Lobjet InternetAddress reprsente une adresse e-mail valide.

134 CHAPITRE 12 Envoyer et recevoir des e-mails

Une exception est leve si vous tentez de crer un objet InternetAddress en utilisant un format dadresse e-mail invalide. Lorsque vous spcifiez les destinataires To, vous devez aussi spcifier leur type. Les types valides sont TO, CC et BCC. Ils sont reprsents par les constantes suivantes : Message.RecipientType.TO Message.RecipientType.CC Message.RecipientType.BCC msg.addRecipient(Message.RecipientType.TO, toAddress); msg.setSubject("Test Message"); msg.setText("This is the body of my message."); Transport.send(msg); La classe Message est une classe abstraite dfinie dans le paquetage javax.mail. Une sous-classe qui limplmente fait partie de limplmentation standard de JavaMail : la classe MimeMessage. Cest cette implmentation que nous utilisons dans lexemple au dbut de la section. La classe MimeMessage reprsente un message lectronique de style MIME. Elle devrait vous suffire pour la plupart de vos besoins en matire de messagerie lectronique. Dans cet exemple, nous utiliserons lobjet Properties pour ne passer que lhte de messagerie SMTP. Il sagit de lunique proprit qu'il est obligatoire de dfinir, mais dautres proprits supplmentaires peuvent aussi tre spcifies.
Info Consultez le sommaire concernant le paquetage javax.mail dans la JavaDoc pour plus de dtails sur dautres proprits de messagerie lies qui peuvent tre passes dans lobjet Properties : http://java.sun.com/javaee/5/docs/api/javax/mail/ package-summary.html.

Envoyer des e-mails MIME

135

Envoyer des e-mails MIME


String html = "<html><head><title>Java Mail</title></head>" + "<body>Some HTML content.</body></html>"; Multipart mp = new MimeMultipart(); BodyPart textPart = new MimeBodyPart( ); textPart.setText("This is the message body."); BodyPart htmlPart = new MimeBodyPart( ); htmlPart.setContent(html, "text/html"); mp.addBodyPart(textPart); mp.addBodyPart(htmlPart); msg.setContent(mp); Transport.send(msg);

MIME est lacronyme de Multimedia Internet Mail Extensions. Ce standard est support par tous les principaux clients de messagerie. Il constitue le moyen standard dassocier des pices jointes aux messages. Il permet de joindre aux e-mails une varit de types de contenu dont des images, des vidos et des fichiers PDF. LAPI JavaMail supporte galement les messages MIME. Il est mme presque aussi facile de crer un message MIME avec des pices jointes quun message standard en texte brut. Dans cet exemple, nous crons et envoyons un message MIME contenant un corps en texte brut et une pice jointe HTML. Pour crer un message multipartie, nous utilisons la classe MultiPart du paquetage javax.mail. La classe MimeMultiPart du paquetage javax.mail.Internet fournit une implmentation concrte de la classe abstraite MultiPart et utilise des conventions MIME pour les donnes multiparties. La classe MimeMultiPart permet dajouter plusieurs parties de corps de message reprsentes sous forme dobjets MimeBodyPart. Le contenu des parties de corps est dfini en utilisant la mthode setText() pour les parties de corps en texte brut et setContent() pour les autres types de parties.

136 CHAPITRE 12 Envoyer et recevoir des e-mails

Ensuite, nous utilisons la mthode setContent() en passant un objet contenant la partie de corps avec une chane spcifiant le type MIME que nous ajoutons. Ici, nous ajoutons une partie de corps HTML et spcifions donc le type MIME text/html. Le code prsent dans lexemple se concentre spcifiquement sur les tapes denvoi du message relatives au standard MIME. Voici un exemple plus complet qui inclut toutes les tapes ncessaires la ralisation de cette tche : Properties props = new Properties( ); props.put("mail.smtp.host", "mail.yourhost.com"); Session session = Session.getDefaultInstance(props, null); Message msg = new MimeMessage(session); msg.setFrom(new InternetAddress("tim@timothyfisher.com")); InternetAddress toAddress = new InternetAddress("kerry@timothyfisher.com"); msg.addRecipient(Message.RecipientType.TO, toAddress); msg.setSubject("Test Message"); String html = "<html><head><title>Java Mail</title> </head>" + "<body>Some HTML content.</body></html>"; Multipart mp = new MimeMultipart(); BodyPart textPart = new MimeBodyPart( ); textPart.setText("This is the message body."); BodyPart htmlPart = new MimeBodyPart( ); htmlPart.setContent(html, "text/html"); mp.addBodyPart(textPart); mp.addBodyPart(htmlPart); msg.setContent(mp); Transport.send(msg);

Lire un e-mail

137

Info LIANA (Internet Assigned Numbers Authority) propose une rfrence prcise de tous les types de contenu MIME standard sur son site Web. Le site propose galement une application permettant denregistrer de nouveaux types MIME. Si vous avez le sentiment quaucun type MIME existant ne correspond votre contenu, vous pouvez utiliser cette application pour demander la cration dun nouveau type de contenu MIME correspondant votre type de contenu. Pour accder au site Web de lIANA, rendez-vous ladresse http://www.iana.org. Les types de contenu MIME peuvent tre trouvs ladresse http://www.iana.org/assignments/media-types/.

Lire un e-mail
Properties props = new Properties(); Session session = Session.getDefaultInstance(props, null); Store store = session.getStore("pop3"); store.connect(host, username, password); Folder folder = store.getFolder("INBOX"); folder.open(Folder.READ_ONLY); Message message[] = folder.getMessages(); for (int i=0, n=message.length; i<n; i++) { System.out.println(i + ": " + message[i].getFrom()[0] + "\t" + message[i].getSubject()); String content = message[i].getContent().toString(); System.out.print(content.substring(0,100)); } folder.close(false); store.close();

Dans cet exemple, nous nous connectons un serveur de messagerie POP3 et rcuprons tous les messages dans le dossier INBOX (bote de rception). LAPI JavaMail facilite considrablement cette tche.

138 CHAPITRE 12 Envoyer et recevoir des e-mails

Voici les tapes gnrales suivre lorsque vous utilisez lAPI JavaMail pour lire des messages depuis un serveur de messagerie POP : 1. Vous devez obtenir un objet Session. 2. Vous devez obtenir un objet Store partir de lobjet Session. 3. Vous devez crer un objet Folder pour le dossier que vous souhaitez ouvrir. 4. Vous devez ouvrir le dossier et rcuprer les messages. Un dossier peut contenir des sous-dossiers : il convient donc de rcuprer galement les messages de ces dossiers en procdant de manire rcursive. Dans cet exemple, nous obtenons une instance par dfaut de lobjet Session en utilisant la mthode statique getDefaultInstance(). Lobjet Session reprsente une session de messagerie. A partir de cet objet, nous obtenons ensuite un objet Store qui implmente le protocole POP3. Lobjet Store reprsente un entrept de messages et son protocole daccs. Si par exemple, nous souhaitions nous connecter un serveur de messagerie IMAP au lieu dun serveur POP3, nous pourrions modifier cette ligne de code afin dobtenir un entrept IMAP au lieu dun entrept POP3. Nous devrions galement inclure un fichier JAR supplmentaire qui supporte le protocole IMAP. Sun fournit le fichier imap.jar dans le cadre de la distribution JavaMail. Nous nous connectons un entrept POP3 en appelant la mthode connect() de lobjet Store et en passant un hte, un nom dutilisateur et un mot de passe.

Lire un e-mail

139

Dans le reste de lexemple, nous rcuprons le dossier INBOX et tous les messages quil contient. Nous imprimons lexpditeur (From), lobjet du message et les cent premiers caractres du corps de chaque message dans le dossier INBOX. La classe Folder contient galement une mthode list() qui nest pas utilise dans cet exemple mais permet de rcuprer un tableau dobjets Folder reprsentant tous les sous-dossiers du dossier sur lequel elle est appele. Si le dossier INBOX contient de nombreux sous-dossiers, il est ainsi possible dobtenir une rfrence chacun dentre eux laide du code suivant : Folder folder = store.getFolder("INBOX"); folder.open(Folder.READ_ONLY); Folder[] subfolders = folder.list(); Le tableau subfolders de cet exemple contiendra un objet Folder pour chaque sous-dossier du dossier INBOX. Il sera alors possible de traiter les messages dans chacun dentre eux, comme nous lavons fait pour ceux du dossier INBOX. La classe Folder propose aussi une mthode getFolder() qui prend un unique paramtre de chane et retourne un dossier dont le nom correspond la chane passe. Grce la classe Folder, vous pouvez crire une mthode qui parcourt lensemble dun compte de messagerie et lit les messages des diffrents dossiers de lutilisateur.

13
Accs aux bases de donnes
Les bases de donnes fournissent un mcanisme de stockage persistant pour les donnes dapplication et dans bien des cas de figure, elles sont essentielles au fonctionnement des applications. Le Java propose un excellent support pour laccs aux bases de donnes relationnelles avec lAPI JDBC (Java Database Connectivity). Si votre application ne dfinit quun modle de donnes trs simple et ne requiert quun accs trs limit une base de donnes, lAPI JDBC convient bien. Au-del de ce cas de figure, il peut cependant tre judicieux de considrer lemploi dun framework de base de donnes plutt que de programmer directement lAPI JDBC. Le framework de persistance standard pour les applications dentreprise est le framework EJB (Enterprise Java Beans). EJB fait partie de Java Enterprise Edition. Il est considr comme tant excessivement complexe par bon nombre de dveloppeurs Java. Ce dfaut a dailleurs fait le succs

142 CHAPITRE 13 Accs aux bases de donnes

de certaines solutions open source qui deviennent de plus en plus populaires. La complexit dEJB et les problmes qui lui taient associs ont heureusement t partiellement rsolus dans EJB 3.0. EJB 3.0 constitue une avance majeure dans la bonne direction et devrait faire dEJB une technologie plus conviviale pour les dveloppeurs. Lexcellent framework de persistance de donnes open source Hibernate gagne sans cesse en popularit. Il cre une couche de mapping objet de vos donnes relationnelles. La couche de mapping objet permet de traiter les donnes persistantes avec une approche oriente objet par opposition linterface SQL procdurale. Pour plus dinformations sur le framework Hibernate, rendez-vous ladresse http://www.hibernate.org. Ce chapitre se concentre purement sur laccs aux bases de donnes via JDBC. Si vous utilisez un framework de persistance de plus haut niveau, il reste important de bien comprendre lAPI JDBC, car elle dfinit les fondations sur lesquelles sappuient la plupart des frameworks de plus haut niveau.

Se connecter une base de donnes via JDBC


Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Connection conn = DriverManager.getConnection(url, user, password);

Pour crer une connexion de base de donnes avec JDBC, vous devez dabord charger un pilote. Dans cet exemple, nous chargeons le JdbcOdbcDriver. Ce pilote fournit une connectivit une source de donnes ODBC.

Se connecter une base de donnes via JDBC

143

Nous le chargeons avec la mthode Class.forName(). Les pilotes de base de donnes JDBC sont gnralement fournis par les diteurs de bases de donnes, bien que Sun propose plusieurs pilotes gnriques dont le pilote ODBC utilis dans cet exemple. Une fois le pilote charg, nous obtenons une connexion la base de donnes avec la mthode DriverManager.getConnection(). La syntaxe utilise pour spcifier la base de donnes laquelle nous souhaitons nous connecter prend la forme dune URL. Nous passons galement un nom dutilisateur et un mot de passe valides pour la connexion la base de donnes. LURL doit commencer par le prfixe jdbc:. Le reste du format de spcification dURL (aprs le prfixe) est spcifique lditeur. Voici la syntaxe dURL pour se connecter une base de donnes ODBC : jdbc:odbc:nomdebasededonnes La plupart des pilotes requirent que la chane dURL inclue un nom dhte, un port et un nom de base de donnes. Voici par exemple une URL valide pour la connexion une base de donnes MySQL : jdbc:mysql://db.myhost.com:3306/mydatabase Cette URL spcifie une base de donnes MySQL sur lhte db.myhost.com pour une connexion sur le port 3306 avec le nom de base de donnes mydatabase. Le format gnral dune URL de base de donnes MySQL est le suivant : jdbc:mysql://hte:port/base de donnes Lun des autres moyens dobtenir une connexion de base de donnes consiste utiliser JNDI. Cest en gnral lapproche que vous adopterez si vous utilisez un serveur dapplications comme WebLogic de BEA ou WebSphere dIBM.

144 CHAPITRE 13 Accs aux bases de donnes

Hashtable ht = new Hashtable(); ht.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); ht.put(Context.PROVIDER_URL, "t3://hostname:port"); Context ctx = new InitialContext(ht); javax.sql.DataSource ds = (javax.sql.DataSource) ctx.lookup("myDataSource"); Connection conn = ds.getConnection();

Avec JNDI, nous crons une instance InitialContext et lutilisons pour rechercher un DataSource. Ensuite, nous obtenons la connexion depuis lobjet de source de donnes. Une autre version de la mthode getConnection() permet aussi de passer un nom dutilisateur et un mot de passe pour la connexion aux bases de donnes requrant une authentification. Il est important de toujours veiller fermer la connexion en utilisant la mthode close() de la classe Connection lorsque vous avez termin dutiliser linstance Connection.

Envoyer une requte via JDBC


Statement stmt = conn.createStatement( ); ResultSet rs = stmt.executeQuery("SELECT * from users where name=tim");

Dans cet exemple, nous crons une instruction JDBC avec la mthode createStatement() de lobjet Connection et lutilisons pour excuter une requte qui retourne un ResultSet Java. Pour la cration de la connexion, rfrez-vous au prcdent exemple, "Se connecter une base de donnes via JDBC". Pour raliser la requte SELECT, nous utilisons la mthode executeQuery() de lobjet Statement.

Envoyer une requte via JDBC

145

Si vous souhaitez effectuer une opration UPDATE au lieu dune requte SELECT, vous devez utiliser la mthode executeUpdate() de lobjet Statement au lieu de sa mthode executeQuery(). La mthode executeUpdate() est utilise avec des instructions SQL INSERT, UPDATE et DELETE. Elle retourne le compte des lignes pour les instructions INSERT, UPDATE ou DELETE ou 0 si linstruction SQL ne retourne rien. Voici un exemple dexcution dune instruction UPDATE : Statement stmt = conn.createStatement( ); int result = stmt.executeUpdate("UPDATE users SET name= tim where id=1234"); Il est important de se souvenir quil nest possible douvrir quun seul objet ResultSet la fois par objet Statement. Toutes les mthodes dexcution dans linterface Statement ferment lobjet ResultSet courant sil en existe dj un douvert. Ce point est important retenir si vous imbriquez des connexions et des requtes de base de donnes. JDBC 3.0 a introduit une fonctionnalit de conservation du jeu de rsultats. Elle permet de conserver plusieurs jeux de rsultats ouverts si vous spcifiez cette option lorsque lobjet dinstruction est cr. Pour en apprendre plus sur les nouvelles fonctionnalits de JDBC 3.0, consultez larticle suivant (en anglais) sur le site Web DeveloperWorks dIBM : http://www.128.ibm.com/developerworks/java/ library/j-jdbcnew/. Lorsque vous travaillez avec des instructions et des rsultats, veillez toujours bien fermer les objets Connection, Statement et ResultSet lorsque vous en avez termin. Chacun de ces objets possde une mthode close() permettant de le fermer afin de librer la mmoire et les ressources. Si vous omettez de les fermer, vous risquez de crer des fuites mmoire dans vos applications Java.

146 CHAPITRE 13 Accs aux bases de donnes

Le fait de ne pas fermer une connexion peut galement provoquer des cas dinterblocage dans les applications multithreades. Si lune de vos instructions SQL doit tre excute de nombreuses fois, il est plus efficace dutiliser une requte PreparedStatement. Pour plus dinformations ce sujet, consultez lexemple suivant, "Utiliser une instruction prpare".

Utiliser une instruction prpare


PreparedStatement stmnt = conn.prepareStatement("INSERT into users values (?,?,?,?)"); stmnt.setString(1, name); stmnt.setString(2, password); stmnt.setString(3, email); stmnt.setInt(4, employeeId); stmnt.executeUpdate( );

Pour crer une instruction prpare dans JDBC, vous devez utiliser un objet PreparedStatement au lieu dun objet Statement. Dans cet exemple, nous passons le code SQL la mthode prepareStatement() de lobjet Connection. Cette opration cre un objet PreparedStatement. Avec une instruction prpare, les valeurs de donnes dans linstruction SQL sont spcifies laide de points dinterrogation. Les vritables valeurs pour ces jokers reprsents par des points dinterrogation sont dfinies plus tard en utilisant les mthodes set de PreparedStatement. Les mthodes set disponibles sont setArray(), setAsciiStream(), setBigDecimal(), setBinaryStream(), setBlob(), setBoolean(), setByte(), setBytes(), setCharacterStream(), setClob(), setDate(), setDouble(), setFloat(), setInt(), setLong(), setNull(), setObject(),

Utiliser une instruction prpare

147

setRef(), setShort(), setString(), setTime(), setTimestamp() et setURL(). Chacune de ces mthodes set est uti-

lise pour dfinir un type de donnes spcifique sous forme de paramtre dans linstruction SQL. Par exemple, la mthode setInt() est utilise pour dfinir des paramtres entiers, la mthode setString() pour dfinir des paramtres String, etc. Dans cet exemple, nous positionnons trois valeurs de chane et une valeur entire avec les mthodes setString() et setInt(). Chaque point dinterrogation qui apparat dans linstruction de requte doit avoir une instruction set correspondante qui dfinisse sa valeur. Le premier paramtre des instructions set spcifie la position du paramtre correspondant dans linstruction de requte. Si la valeur 1 est passe comme premier paramtre une instruction set, cest ainsi la valeur correspondant au premier point dinterrogation qui est positionne dans linstruction de requte. Le second paramtre des instructions set spcifie la valeur elle-mme du paramtre. Dans notre exemple, les variables name, password et email sont toutes censes tre de type String. La variable employeeId est de type int. Lorsque vous crez une instruction SQL que vous allez rutiliser plusieurs fois, il est plus efficace dutiliser un objet PreparedStatement au lieu dun objet Statement standard. Linstruction prpare est une instruction SQL prcompile qui offre une excution plus rapide une fois cre.

148 CHAPITRE 13 Accs aux bases de donnes

Rcuprer les rsultats dune requte


ResultSet rs = stmt.executeQuery("SELECT name, password FROM users where name=tim"); while (rs.next( )) { String name = rs.getString(1); String password = rs.getString(2); }

Les requtes JDBC retournent un objet ResultSet. Ce dernier reprsente une table de donnes contenant les rsultats dune requte de base de donnes. Le contenu du ResultSet peut tre parcouru afin dobtenir les rsultats de la requte excute. Le ResultSet conserve un curseur qui pointe sur la ligne de donnes courante. Lobjet ResultSet possde une mthode next() qui dplace le curseur la ligne suivante. La mthode next() retourne false lorsquil ny a plus de ligne dans lobjet ResultSet. Il est ainsi possible dutiliser une boucle while pour parcourir toutes les lignes contenues dans le ResultSet. Le ResultSet possde des mthodes getter permettant de rcuprer les valeurs de colonne de la ligne courante. Les valeurs de donnes peuvent tre rcupres laide du numro dindex ou du nom de la colonne. La numrotation des colonnes commence 1. La casse nest pas prise en compte pour les noms de colonne fournis en entre aux mthodes getter. Dans cet exemple, nous obtenons un ResultSet suite lexcution dune requte SELECT. Nous parcourons en boucle les lignes contenues dans le ResultSet en utilisant la mthode next() et une boucle while. Nous obtenons les valeurs de donnes name et password avec la mthode getString().

Utiliser une procdure stocke

149

Rappelez-vous quil est conseill de fermer vos instances de ResultSet lorsque vous avez fini de les utiliser. Les objets ResultSet sont automatiquement ferms lorsque lobjet Statement qui les a gnrs est ferm, rexcut ou utilis pour rcuprer le rsultat suivant dune squence de rsultats multiples.

Utiliser une procdure stocke


CallableStatment cs = conn.prepareCall("{ call ListAllUsers }"); ResultSet rs = cs.executeQuery( );

Les procdures stockes sont des programmes de base de donnes stocks et conservs dans la base de donnes elle-mme. Elles peuvent tre appeles depuis le code Java en utilisant linterface CallableStatement et la mthode prepareCall() de lobjet Connection. CallableStatement retourne un objet ResultSet comme le fait Statement ou PreparedStatement. Dans cet exemple, nous appelons la procdure stocke ListAllUsers sans paramtre. Lobjet CallableStatement peut prendre des paramtres dentre galement. Ceux-ci sont grs exactement comme ils le sont avec un PreparedStatement. Par exemple, le code suivant montre comment appeler une procdure stocke qui utilise des paramtres dentre : CallableStatment cs = conn.prepareCall("{ call AddInts(?,?) }"); cs.setInt(1,10); cs.setInt(2,50); ResultSet rs = cs.executeQuery( );

150 CHAPITRE 13 Accs aux bases de donnes

A la diffrence des autres types dinstructions JDBC, CallableStatement peut galement retourner des paramtres, appels paramtres OUT. Le type JDBC de chaque paramtre OUT doit tre enregistr avant que lobjet CallableStatement puisse tre excut. Cette inscription sopre avec la mthode registerOutParameter(). Une fois que linstruction a t excute, les paramtres OUT peuvent tre rcuprs en utilisant les mthodes getter de CallableStatement. CallableStatement cs = con.prepareCall("{call getData(?, ?)}"); cs.registerOutParameter(1, java.sql.Types.INT); cs.registerOutParameter(2, java.sql.Types.STRING); ResultSet rs = cs.executeQuery(); int intVal = cs.getInt(1); String strVal = cs.getString(2); Dans cet exemple, nous appelons une procdure stocke nomme getData() qui possde deux paramtres OUT. Lun de ces paramtres OUT est une valeur int et lautre une valeur String. Une fois ces deux paramtres enregistrs, nous excutons la requte et obtenons leurs valeurs avec les mthodes getInt() et getString(). Lune des autres diffrences remarquer tient ce que les procdures stockes peuvent retourner plusieurs jeux de rsultats. Si une procdure stocke retourne plus dun jeu de rsultats, on peut utiliser la mthode getMoreResults() de la classe CallableStatement pour fermer le jeu de rsultats courant et pointer sur le suivant. La mthode getResultSet() peut tre appele ensuite pour rcuprer le jeu de rsultats nouvellement dsign.

Utiliser une procdure stocke

151

Voici un exemple qui retourne plusieurs jeux de rsultats et utilise ces mthodes pour rcuprer chacun dentre eux : int i; String s; callablestmt.execute(); rs = callablestmt.getResultSet(); while (rs.next()) { i = rs.getInt(1); } callablestmt.getMoreResults(); rs = callablestmt.getResultSet(); while (rs.next()) { s = rs.getString(1); } rs.close(); callablestmt.close(); Ici, nous positionnons la valeur int i avec les rsultats du premier jeu de rsultats et la variable String s avec ceux du second.

14
XML
Le XML (eXtensible Markup Language) est driv du SGML (Standard Generalized Markup Language), tout comme le HTML (Hypertext Markup Language). En fait, le XML est mme analogue en bien des points au HTML, ceci prs quen XML, il vous revient de dfinir vos propres balises. Vous ntes pas cantonn un jeu prdfini de balises comme vous ltes en HTML. Le XHTML, pour sa part, est une version du HTML compatible avec le standard XML. Le XML est couramment utilis comme format gnrique pour lchange de donnes entre serveurs et applications, dans les processus de communication entre couches applicatives ou pour le stockage de donnes complexes comme les documents de traitement de texte voir les fichiers graphiques. Le XML a t largement adopt dans tous les secteurs dindustrie et par la majorit des langages de programmation. La plupart dentre eux proposent maintenant un support pour le traitement des donnes XML. Le Java ny fait pas exception et fournit dexcellents outils pour le traitement des documents XML, que ce soit pour crer ou pour lire des donnes XML.

154 CHAPITRE 14 XML

Ce chapitre requiert des connaissances en XML. Si vous souhaitez apprendre ce langage ou parfaire vos connaissances dans ce domaine, consultez XML de Michael Morrison (CampusPress, 2006). Deux API de parsing XML courantes indpendantes du langage sont dfinies par le W3C (World Wide Web Consortium) : les API DOM et SAX. Le DOM (Document Object Model) est un parseur qui lit un document XML entier et construit un arbre dobjets Node, que lon appelle le DOM ou le modle objet du document. Le DOM livre une reprsentation parse complte du document XML dont vous pouvez extraire des lments tout moment. SAX (Simple API for XML) nest pas un vritable parseur en soi, mais plus exactement une API qui dfinit un mcanisme de gestion des vnements pouvant servir parser des documents XML. Vous pouvez crer des mthodes de rappel qui sont appeles par lAPI SAX au moment o des lments spcifiques du document XML sont atteints. Limplmentation SAX scanne le document XML en appelant les mthodes de rappel ds quelle rencontre le dbut et la fin dlments particuliers du document XML. Avec SAX, le document XML nest jamais compltement stock ou reprsent en mmoire. Limplmentation Java du traitement XML est appele JAXP (Java API for XML Processing). JAXP permet aux applications de parser et de transformer des documents XML sans laide dune implmentation de traitement XML. JAXP contient un parseur DOM et un parseur SAX ainsi quune API XSLT pour la transformation des documents XML. XSLT est lacronyme de eXtensible Stylesheet Language Transformations. La technologie XSLT permet de transformer les documents XML en les faisant passer dun format un autre. JAXP fait partie intgrante du JDK 1.4 et de ses versions ultrieures.

Parser du XML avec SAX

155

Parser du XML avec SAX


XMLReader parser = XMLReaderFactory.createXMLReader ("org.apache.xerces.parsers.SAXParser"); parser.setContentHandler(new MyXMLHandler( )); parser.parse("document.xml");

LAPI SAX opre en scannant le document XML de bout en bout et en fournissant des rappels pour les vnements qui se produisent. Ces vnements peuvent correspondre la rencontre du dbut dun lment, de sa fin, du dbut dun attribut, de sa fin, etc. Ici, nous crons une instance XMLReader en utilisant le SAXParser. Une fois linstance de parseur cre, nous dfinissons un gestionnaire de contenu avec la mthode setContentHandler(). Le gestionnaire de contenu est une classe qui dfinit les diffrentes mthodes de rappel appeles par le parseur SAX lorsque le document XML est pars. Ici, nous crons une instance de MyXMLHandler, une classe que nous allons devoir ensuite implmenter, en guise de gestionnaire. Ensuite, nous appelons la mthode parse() et lui passons le nom dun document XML. Ds lors, le traitement SAX dmarre. Le code suivant prsente une implmentation dexemple de la classe MyXMLHandler. La classe DefaultHandler que nous tendons est une classe de base par dfaut pour les gestionnaires dvnements SAX. class MyXMLHandler extends DefaultHandler { public void startElement(String uri, String localName, String qname, Attributes attributes) { // Traiter le dbut de llment }
public void endElement(String uri, String localName, String qname) {

156 CHAPITRE 14 XML

// Traiter la fin de llment } public void characters(char[] ch, int start, int length) { // Traiter les caractres } public MyXMLHandler( ) throws org.xml.sax.SAXException { super( ); } }

Cette implmentation dexemple nimplmente que trois mthodes : startElement(), endElement() et characters(). La mthode startElement() est appele par le parseur SAX lorsquil rencontre le dbut dun lment dans le document XML. De la mme manire, la mthode endElement() est appele lorsquil rencontre la fin dun lment. La mthode characters() est appele pour signaler la prsence de donnes de caractre dans un lment. Pour obtenir une description complte de toutes les mthodes qui peuvent tre redfinies dans le gestionnaire SAX, consultez la JavaDoc DefaultHandler : http://java.sun.com/j2se/1.5.0/ docs/api/org/xml/sax/helpers/DefaultHandler.html. Dans cet exemple, le parseur SAX sous-jacent est Xerces. Nous le dfinissons dans lappel de mthode suivant : XMLReader parser = XMLReaderFactory.createXMLReader ("org.apache.xerces.parsers.SAXParser"); JAXP est conu pour permettre des implmentations de parseur externes : si vous prfrez un autre parseur Xerces, rien ne vous empche de lutiliser avec le code

Parser du XML avec DOM

157

de cet exemple. Veillez cependant bien inclure limplmentation du parseur dans votre chemin de classe. SAX est gnralement plus efficace au niveau de la mmoire que le parseur DOM car le document XML nest pas tout entier stock en mmoire. LAPI DOM lit le document entier en mmoire pour le traiter.

Parser du XML avec DOM


File file = new File("document.xml"); DocumentBuilderFactory f = DocumentBuilderFactory.newInstance(); DocumentBuilder p = f.newDocumentBuilder(); Document doc = p.parse(file);

Dans cet exemple, nous utilisons les trois classes DocumentBuilderFactory, DocumentBuilder et Document pour dmarrer le parsing dun document XML avec un parseur DOM. Le parsing sopre avec la classe DocumentBuilder. Cette dernire dfinit lAPI permettant dobtenir des instances de Document DOM partir dun document XML. La classe DocumentBuilder peut parser du XML depuis une varit de sources dentre, dont des InputStream, des File, des URL et des SAXInputSources. Ici, nous parsons le XML partir dune source dentre File. La mthode parse() de la classe DocumentBuilder parse le document XML et retourne un objet Document. Lobjet Document reprsente le DOM du document XML. Cette instance Document peut ensuite tre utilise pour accder aux composants du document XML, comme ses entits, ses lments, ses attributs, etc.

158 CHAPITRE 14 XML

Lobjet Document est un conteneur pour une collection hirarchique dobjets Node qui reprsente la structure du document XML. Les nuds ont un parent, des enfants ou des attributs associs. Le type Node contient trois sousclasses qui reprsentent les principaux composants du document XML : Element, Text et Attr. Considrons maintenant un exemple de parsing dun DOM avec la classe Document. Voici le document XML dexemple que nous allons utiliser : <Location> <Address> <City>Flat Rock</City> <State>Michigan</State> </Address> </Location> En supposant que nous avons dj obtenu une instance Document avec la technique de parsing prsente dans lexemple de dpart, il suffira dutiliser le code Java suivant pour extraire les valeurs de texte de villes (city) et dtats (state) : NodeList list = document.getElementsByTagName("City"); Element cityEl = (Element)list.item(0); String city = ((Text)cityEl.getFirstChild()).getData(); NodeList list = document.getElementsByTagName("State"); Element stateEl = (Element)list.item(0); String state = ((Text)stateEl.getFirstChild()).getData(); La mthode getElementsByTagName() retourne un NodeList contenant tous les lments qui correspondent au nom pass. Notre document dexemple ne contient quun seul lment City et un seul lment State : nous rcuprons

Utiliser une DTD pour vrifier un document XML

159

donc simplement le premier lment (index zro) de la liste de nuds et le transtypons en un Element. Les lments City et State possdent chacun un enfant, de type Text. Nous utilisons la mthode getData() du type Text pour rcuprer la valeur de ville (city) et dtat (state). A la diffrence du parseur SAX, le parseur DOM lit le document XML entier en mmoire, le parse et le traite cet endroit. Ce procd est moins efficace en termes de consommation de mmoire que celui du parseur SAX qui ne stocke pas le document XML entier en mmoire mais le scanne progressivement la manire dun flux.

Utiliser une DTD pour vrier un document XML


DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(true); DocumentBuilder builder = factory.newDocumentBuilder();

Les DTD (Document Type Definition) sont des fichiers qui dfinissent la manire dont un document XML particulier doit tre structur. Une DTD peut ainsi spcifier quels lments et quels attributs sont autoriss dans un document. Les documents XML qui se conforment une DTD sont considrs tre valides. Les documents XML syntaxiquement corrects mais qui ne se conforment pas une DTD sont simplement dits bien forms. Pour valider un document avec une DTD, vous devez appeler la mthode setValidating() de linstance DocumentBuilderFactory et lui passer la valeur true. Tous les documents XML parss sont ensuite valids par rapport

160 CHAPITRE 14 XML

aux DTD spcifies dans leur en-tte. Voici une dclaration de DTD classique en haut dun document XML : <!DOCTYPE people SYSTEM "file:baseball.dtd"> Cette dclaration attache le fichier baseball.dtd stock dans le systme de fichiers local sous forme de DTD au document XML dans lequel elle est dclare. Lorsque vous spcifiez la validation DTD, une exception est lance depuis la mthode parse() de la classe DocumentBuilder si le document XML que vous parsez ne se conforme pas la DTD. Le standard XML Schema est une technologie plus rcente qui offre les mmes avantages que les DTD. Les schmas XML dfinissent le balisage attendu des documents XML, comme le font les DTD. Lavantage des documents de schma tient cependant ce quils sont eux-mmes des documents XML et que vous navez donc pas besoin dun autre parseur pour les lire, alors que les DTD ne sont pas des documents XML valides. Les DTD respectent la syntaxe XBNF (eXtended Backus-Naur Form). Pour utiliser un schma, vous devez utiliser la mthode setSchema() du DocumentBuilderFactory au lieu de la mthode setValidating(), comme ceci : DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setSchema(schema); DocumentBuilder builder = factory.newDocumentBuilder(); La mthode setSchema() prend une instance dun objet Schema. Nous nentrerons pas ici dans les considrations de dtail concernant lutilisation des schmas, mais vous pouvez consulter la JavaDoc de DocumentBuilderFactory pour plus dinformations sur limplmentation des schmas

Crer un document XML avec DOM

161

en Java, ladresse suivante : http://java.sun.com/j2se/ 1.5.0/docs/api/javax/xml/parsers/DocumentBuilderFactory.html. Pour plus dinformations sur les schmas en gnral, consultez la documentation XML Schema ladresse : http://www.w3.org/TR/xmlschema-1/.

Crer un document XML avec DOM


DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance( ); DocumentBuilder builder = fact.newDocumentBuilder( ); Document doc = builder.newDocument( ); Element location = doc.createElement("Location"); doc.appendChild(location); Element address = doc.createElement("Address"); location.appendChild(address); Element city = doc.createElement("City"); address.appendChild(city); line.appendChild(doc.createTextNode("Flat Rock")); Element state = doc.createElement("State"); address.appendChild(state); state.appendChild(doc.createTextNode("Michigan")); ((org.apache.crimson.tree.XmlDocument)doc) .write(System.out);

Cet exemple utilise lAPI DOM et JAXP pour crer un document XML. Le segment XML cr est le suivant : <Location> <Address> <City>Flat Rock</City> <State>Michigan</State> </Address> </Location>

162 CHAPITRE 14 XML

La principale classe utilise ici est la classe org.w3c.dom .Document. Elle reprsente le DOM dun document XML. Nous crons une instance de la classe Document en utilisant un DocumentBuilder obtenu partir dun DocumentBuilderFactory. Chaque lment du document XML est reprsent dans le DOM sous forme dinstance Element. Dans le document XML que nous crons, nous avons construit des objets Element appels Location, Address, City et State. Nous ajoutons llment de niveau racine (Location) lobjet de document avec la mthode appendChild() de lobjet Document. La classe Element contient elle aussi une mthode appendChild() que nous utilisons pour construire la hirarchie du document sous llment racine. LAPI DOM permet tout aussi facilement de crer un Element avec des attributs. Le code suivant peut tre utilis pour ajouter un attribut "id" possdant la valeur "home" llment Location : location.setAttribute("id","home"); Dans cet exemple, le parseur DOM sous-jacent est Crimson. Cette implmentation apparat dans la dernire ligne, reproduite ici : ((org.apache.crimson.tree.XmlDocument)doc) .write(System.out); JAXP est conu pour supporter les implmentations de parseur externes : si vous prfrez un autre parseur Crimson, rien ne vous empche de lutiliser avec le code de cet exemple. Veillez cependant bien inclure limplmentation du parseur dans votre chemin de classe. LAPI JDOM est une alternative lAPI JAXP pour le travail avec les documents XML. Il sagit dun projet open source standardis par le biais du JCP (Java Community

Transformer du XML avec des XSLT

163

Process), sous la rfrence JSR 102. Pour plus dinformations sur lAPI JDOM, consultez le site www.jdom.org. JDOM propose une API Java native en remplacement de lAPI DOM standard pour lire et crer des documents XML. De nombreux dveloppeurs trouvent lAPI JDOM plus facile utiliser que lAPI DOM lors de la cration de documents XML.

Transformer du XML avec des XSLT


StreamSource input = new StreamSource(new File("document.xml")); StreamSource stylesheet = new StreamSource(new File("style.xsl")); StreamResult output = new StreamResult(new File("out.xml")); TransformerFactory tf = TransformerFactory.newInstance(); Transformer tx = tf.newTransformer(stylesheet); tx.transform(input, output);

Le XSLT est un standard pour la transformation des documents XML qui permet den modifier la structure laide de feuilles de style XSL. Le paquetage javax.xml.transform contient lAPI permettant dutiliser des transformations XSLT standard en Java. XSL est lacronyme de eXtensible Stylesheet Language. XSLT est lacronyme de XSL Transformation (transformation XSL), un langage qui permet de restructurer compltement les documents XML. Lorsque vous utiliserez des XSLT, vous aurez en gnral un document XML dentre et une feuille de style XSL dentre et produirez en les combinant un document XML de sortie. Le type du document de sortie ne se limite cependant pas au XML. Bien dautres sortes de documents de sortie peuvent tre cres laide de transformations XSL.

164 CHAPITRE 14 XML

Dans cet exemple, nous crons des instances StreamSource pour les documents utiliss en entre du processus de transformation : le document XML transformer et la feuille de style XSL contenant les instructions de transformation. Nous crons aussi un objet StreamResult qui servira recueillir le rsultat de lcriture du document de sortie. Nous obtenons ensuite une instance Transformer gnre partir dune instance TranformerFactory. Le flux de feuille de style est ensuite pass la mthode newTranformer() de lobjet TransformerFactory pour crer un objet Transformer. Pour finir, nous appelons la mthode transform() du Transformer afin de transformer notre document XML dentre en un document de sortie mis en forme avec la feuille de style slectionne. Le XSL peut tre une technologie trs efficace pour les dveloppeurs. Si votre application Web doit tre accessible partir dune varit de priphriques diffrents, comme des assistants personnels, des navigateurs Web et des tlphones cellulaires, vous pourrez ainsi utiliser des XSLT pour transformer votre sortie afin den adapter le format chacun des priphriques concerns, sans programmer chaque fois une sortie spare. Les XSLT sont aussi trs utiles pour crer des sites multilingues. La sortie XML peut en effet tre transforme en plusieurs langages grce des transformations XSLT.

15
Utiliser des threads
Le threading dsigne la mthode utilise par une application logicielle pour accomplir plusieurs processus la fois. En Java, un thread est une unit dexcution programme qui sexcute simultanment dautres threads. Les threads sont frquemment utiliss dans les applications dinterface utilisateur graphique (GUI). Dans une application de ce type, un thread peut couter lentre du clavier ou dautres priphriques de saisie pendant quun autre traite la commande prcdente. La communication rseau implique aussi souvent lusage du multithreading. En programmation rseau, un thread peut couter les requtes de connexion, pendant quun autre traite une requte prcdente. Les minuteurs utilisent aussi couramment les threads. Ils peuvent tre dmarrs sous forme de thread sexcutant indpendamment du reste de lapplication. Dans tous ces exemples, le multithreading permet une application de poursuivre le traitement tout en excutant une autre tche qui peut prendre plus de temps et provoquerait de longs dlais en labsence de multithreading.

166 CHAPITRE 15 Utiliser des threads

Le Java facilite grandement lcriture dapplications multithreades. La conception dapplications multithreades tait trs complexe en C, mais en Java, tout est bien plus simple.

Lancer un thread
public class MyThread extends Thread { public void run() { // Excuter des tches } } // Code pour utiliser MyThread new MyThread().start();

Il existe deux techniques principales pour crire du code qui sexcute dans un thread spar. Vous pouvez implmenter linterface java.lang.Runnable ou tendre la classe java.lang.Thread. Dans lun ou lautre cas, vous devez implmenter une mthode run() qui contient le code excuter dans le thread. Dans cet exemple, nous avons tendu la classe java.lang .Thread. A lemplacement o nous souhaitons dmarrer le thread, nous instancions notre classe MyThread et appelons la mthode start() hrite de la classe Thread. Voici maintenant le code permettant dexcuter un thread avec lautre technique, en implmentant linterface Runnable : public class MyThread2 implements Runnable { public void run() { // Excuter des tches } }
// Code pour utiliser MyThread2 Thread t = new Thread(MyThread2); t.start();

Lancer un thread

167

Linterface Runnable est en gnral implmente lorsquune classe tend une autre classe et ne peut donc tendre la classe Thread galement. Le Java ne supporte que lhritage unique : une classe ne peut tendre deux classes diffrentes. La mthode lintrieur de laquelle nous dmarrons le thread est ici lgrement diffrente. Au lieu dinstancier la classe prcdemment dfinie, comme nous lavons fait en tendant linterface Thread, nous instancions un objet Thread et passons la classe implmentant Runnable en paramtre au constructeur Thread. Ensuite, nous appelons la mthode start() de Thread, qui dmarre le thread et planifie son excution. Lun des autres moyens pratiques de crer un thread consiste implmenter linterface Runnable en utilisant une classe interne anonyme, comme ceci : public class MyThread3 { Thread t;
public static void main(String argv[]) { new MyThread3(); } public MyThread3() { t = new Thread(new Runnable( ) { public void run( ) { // Excuter des tches } }); t.start( ); } }

168 CHAPITRE 15 Utiliser des threads

Dans cet exemple, tout le code est contenu lintrieur dune unique classe et se trouve donc parfaitement encapsul. On peut ainsi mieux voir ce qui se passe. Notre implmentation Runnable est dfinie sous forme de classe interne au lieu de crer explicitement une classe qui implmente linterface Runnable. Cette solution est idale pour les petites mthodes qui ninteragissent que trs peu avec des classes externes.

Arrter un thread
public class StoppableThread extends Thread { private boolean done = false; public void run( ) { while (!done) { System.out.println("Thread running"); try { sleep(500); } catch (InterruptedException ex) { // Ne rien faire } } System.out.println("Thread finished."); } public void shutDown( ) { done = true; } }

Si vous souhaitez crer un thread que vous pourrez arrter avant la fin de son excution (autrement dit, avant le retour de la mthode run()), la meilleure solution consiste utiliser un drapeau boolen dont vous testerez ltat au dbut

Attendre quun thread se termine

169

dune boucle globale. Dans cet exemple, nous crons un thread en tendant la classe Thread avec notre classe StoppableThread. A lintrieur de la mthode run(), nous crons une boucle while qui vrifie ltat dun drapeau boolen done. Tant que le drapeau done vaut false, le thread continue. Pour arrter le thread, il suffit un processus externe de positionner le drapeau true. La boucle while de la mthode run() quitte alors et termine ce thread. La classe Thread contient une mthode stop() que lon peut tre tent dutiliser pour arrter le thread, mais Sun en dconseille lusage, car si votre thread opre sur un objet de structure de donnes et que vous appelez soudainement sa mthode stop(), les objets peuvent tre laisss dans un tat incohrent. Si dautres threads attendent que cet objet particulier soit libr, ils risquent alors de se bloquer et dattendre indfiniment. Des problmes dinterblocage peuvent avoir lieu. La mthode stop() est galement dconseille depuis le JDK 1.2. Si vous utilisez la mthode stop() dans lun de ces JDK, le compilateur gnre des avertissements ce sujet. Larticle de rfrence (en anglais) ladresse suivante explique les raisons pour lesquelles la mthode stop() est dconseille : http://java.sun.com/j2se/1.5.0/docs/ guide/misc/threadPrimitiveDeprecation.html.

Attendre quun thread se termine


Thread t = new Thread(MyThread); t.start(); // Raliser dautres oprations t.join(); // Continue aprs que le thread t se termine

170 CHAPITRE 15 Utiliser des threads

Dans certains cas, vous pourrez souhaiter quun thread dexcution attende quun autre thread ait termin avant de poursuivre. La jonction des threads est une mthode courante pour interrompre un thread jusqu ce quun autre thread ait achev son travail. Dans cet exemple, nous dmarrons le thread t de lintrieur du thread qui excute ces lignes de code. Des oprations sont ensuite excutes, puis nous appelons la mthode join() de lobjet de thread lorsque nous souhaitons arrter lexcution du thread en attendant que le thread t en ait fini. Lorsque t a fini, lexcution se poursuit jusquaux instructions qui suivent la ligne dans laquelle nous avons appel la mthode join(). Si le thread t a dj compltement termin lorsque nous appelons join(), cette dernire retourne immdiatement lexcution. Une autre forme de la mthode join() prend un paramtre long contenant une valeur en millisecondes. Lorsque cette mthode est utilise, le thread appelant attend au maximum le nombre de millisecondes spcifi avant de continuer, mme si le thread sur lequel la mthode join() est appele na pas fini. Enfin, une troisime implmentation de la mthode join() prend deux paramtres, une valeur long en millisecondes et une valeur int en nanosecondes. Cette mthode se comporte exactement comme la version un paramtre, sauf que les valeurs en millisecondes et en nanosecondes sont additionnes pour dterminer la dure pendant laquelle le thread appelant doit attendre avant de continuer. Cette mthode offre un contrle plus fin sur le temps dattente.

Synchroniser des threads

171

Synchroniser des threads


public synchronized void myMethod() { // Excuter quelque chose }

La synchronisation est utilise pour empcher que plusieurs threads puissent accder simultanment des sections spcifiques du code. Le mot-cl synchronized qui apparat dans cet exemple permet de synchroniser une mthode ou un bloc de code afin quun seul thread puisse lexcuter la fois. Dans le contexte de cet exemple, si un thread excute actuellement myMethod(), tous les autres threads qui tentent dexcuter la mme mthode sur la mme instance dobjet sont bloqus lextrieur de la mthode jusqu ce que le thread courant termine son excution et la retourne de myMethod(). Dans le cas des mthodes non statiques, la synchronisation sapplique uniquement linstance dobjet sur laquelle un autre thread excute la mthode. Les autres threads gardent la possibilit dexcuter la mme mthode mais sur une instance diffrente. Au niveau de linstance, le verrouillage sapplique toutes les mthodes synchronises de linstance. Aucun thread ne peut appeler la moindre mthode synchronise dune instance dont un thread excute dj une mthode synchronise. Dans le cas des mthodes statiques, seul un thread la fois peut excuter la mthode. Le mot-cl synchronized peut galement tre appliqu des blocs de code, sans ncessairement concerner lensemble dune mthode. Le bloc de code suivant opre une synchronisation de ce type : synchronized(myObject) { // Faire quelque chose avec myObject }

172 CHAPITRE 15 Utiliser des threads

Lors de la synchronisation dun bloc de code, vous devez spcifier lobjet sur lequel la synchronisation doit tre opre. Bien souvent, le but est doprer la synchronisation sur lobjet qui contient le bloc de code, ce qui peut tre fait en passant lobjet this comme objet synchroniser, comme ceci : synchronized(this) { // Faire quelque chose } Lobjet pass au mot-cl synchronized est verrouill lorsquun thread excute le bloc de code quil entoure. La synchronisation est gnralement utilise lorsque laccs concurrentiel par plusieurs threads peut risquer dendommager des donnes partages. Une classe dite thread-safe garantit quaucun thread nutilise un objet qui se trouve dans un tat incohrent. Le bloc de code suivant prsente un exemple de classe qui risquerait dtre problmatique si elle ntait pas rendue thread-safe en appliquant le mot-cl synchronized la mthode adjust(). En gnral, les classes qui possdent des membres de donnes dinstance sont susceptibles de poser des problmes dans les environnements multithreads. A titre dexemple, supposons que deux threads excutent la mthode adjust() et que cette dernire ne soit pas synchronise. Le thread A excute la ligne size=size+1 et se trouve interrompu juste aprs la lecture de la valeur size, mais avant dattribuer la nouvelle valeur size. Le thread B sexcute maintenant et appelle la mthode reset(). Cette mthode positionne la variable size 0. Le thread B est ensuite interrompu et retourne le contrle au thread A, qui reprend maintenant lexcution de linstruction size=size+1, en incrmentant la valeur de size dune unit. Au final, la mthode reset() ne parat pas avoir t appele. Ses effets sont contrecarrs par les

Synchroniser des threads

173

imprvus du multithreading. Si le mot-cl synchronized est appliqu ces mthodes, ce cas de figure ne se produit plus, car un seul thread est alors autoris excuter lune ou lautre des mthodes. Le deuxime thread doit attendre que le premier ait termin lexcution de la mthode. public class ThreadSafeClass { private int size;
public synchronized void adjust() { size = size + 1; if (size >= 100) { size = 0; } } public synchronized void reset() { size = 0; } }

La programmation thread-safe ne sapplique qu une application qui possde plusieurs threads. Si vous crivez une application qui nutilise pas de multithreading, vos soucis senvolent. Avant dopter pour ce choix, considrez cependant aussi que votre application ou votre composant peuvent tre rutiliss dautres endroits. Quand vous nutilisez quun seul thread, posez-vous cette question : est-il possible quun autre projet utilise ce composant dans un environnement multithread ? La synchronisation peut tre utilise pour rendre un objet thread-safe, mais noubliez pas quelle implique un compromis en termes de performances. Lexcution des mthodes synchronises est consquemment plus lente en raison de la surcharge lie au verrouillage des objets. Veillez ainsi ne synchroniser que les mthodes qui requirent vritablement dtre thread-safe.

174 CHAPITRE 15 Utiliser des threads

Suspendre un thread
MyThread thread = new MyThread(); thread.start(); while (true) { // Quelques tches synchronized (thread) { thread.doWait = true; } // Quelques tches synchronized (thread) { thread.doWait = false; thread.notify(); } } class MyThread extends Thread { boolean doWait = false; public void run() { while (true) { // Quelques tches synchronized (this) { while (doWait) { wait(); } catch (Exception e) { } } } } } }

Suspendre un thread

175

Cet exemple montre comment suspendre un thread depuis un autre thread. Nous utilisons la variable doWait comme drapeau. Dans la mthode run() de MyThread, nous vrifions ltat de ce drapeau aprs avoir ralis une tche dans une boucle afin de dterminer si nous devons suspendre lexcution du thread. Si le drapeau doWait vaut true, nous appelons la mthode Object.wait() pour suspendre lexcution du thread. Lorsque nous souhaitons relancer le thread, nous positionnons le drapeau doWait false et appelons la mthode thread.Notify() pour relancer le thread et poursuivre sa boucle dexcution. La suspension du thread est trs simple raliser, comme le montre le fragment suivant : long numMilliSecondsToSleep = 5000; Thread.sleep(numMilliSecondsToSleep); Ce code suspend le thread courant pendant 5 000 millisecondes, soit 5 secondes. En plus de ces mthodes, deux mthodes appeles Thread.suspend() et Thread.resume() fournissent un mcanisme pour la suspension des threads, mais elles sont dconseilles. Elles peuvent en effet souvent crer des interblocages. Nous ne les mentionnons ici que pour signaler quil convient de ne pas les utiliser.

176 CHAPITRE 15 Utiliser des threads

Lister tous les threads


public static void listThreads() { ThreadGroup root = Thread.currentThread().getThreadGroup().getParent(); while (root.getParent() != null) { root = root.getParent(); } visitGroup(root, 0); } public static void visitGroup(ThreadGroup group, int level) { int numThreads = group.activeCount(); Thread[] threads = new Thread[numThreads]; group.enumerate(threads, false); for (int i=0; i<numThreads; i++) { Thread thread = threads[i]; printThreadInfo(thread); } int numGroups = group.activeGroupCount(); ThreadGroup[] groups = new ThreadGroup[numGroups]; numGroups = group.enumerate(groups, false); for (int i=0; i<numGroups; i++) { visitGroup(groups[i], level+1); } } private static void printThreadInfo(Thread t) { System.out.println("Thread: " + t.getName( ) + " Priority: " + t.getPriority( ) + (t.isDaemon( )?" Daemon":"") + (t.isAlive( )?"":" Not Alive")); }

Cet exemple liste tous les threads en cours dexcution. Chaque thread rside dans un groupe de threads et chaque groupe de threads peut contenir des threads et dautres groupes de threads. La classe ThreadGroup permet de

Lister tous les threads

177

regrouper des threads et dappeler des mthodes qui affectent tous les threads dans le groupe de threads. Les ThreadGroup peuvent galement contenir des ThreadGroup enfants. Les ThreadGroup organisent ainsi tous les threads en une hirarchie complte. Dans cet exemple, nous parcourons en boucle tous les groupes de threads afin dimprimer des informations concernant chacun des threads. Nous commenons par retrouver le groupe de threads racine. Ensuite, nous utilisons la mthode visitGroup() pour consulter de manire rcursive chaque groupe de threads situ sous le groupe racine. Dans la mthode visitGroup(), nous numrons dabord tous les threads contenus dans le groupe puis appelons la mthode printThreadInfo() pour imprimer le nom, la priorit et ltat (dmon ou non, vivant ou non) de chaque thread. Aprs avoir parcouru en boucle tous les threads dans le groupe courant, nous numrons tous les groupes quil contient et oprons un appel rcursif la mthode visitGroup() pour chaque groupe. Cet appel de mthode se poursuit jusqu ce que tous les groupes et tous les threads aient t numrs et que les informations concernant chacun des threads aient t imprimes. Les groupes de threads sont souvent utiliss pour regrouper des threads lis ou similaires, par exemple selon la fonction quils ralisent, leur provenance ou le moment o ils doivent tre dmarrs et arrts.

16
Programmation dynamique par rexion
La rflexion est un mcanisme permettant de dcouvrir lexcution des donnes concernant un programme. En Java, elle permet de dcouvrir des informations concernant des champs, des mthodes et des constructeurs de classes. Vous pouvez aussi oprer sur les champs et mthodes que vous dcouvrez de cette manire. La rflexion permet ainsi de raliser en Java ce que lon appelle couramment une programmation dynamique. La rflexion sopre en Java laide de lAPI Java Reflection. Cette API est constitue de classes dans les paquetages java.lang et java.lang.reflect.

180 CHAPITRE 16 Programmation dynamique par rflexion

Entre autres possibilits, lAPI Java Reflection permet notamment : b de dterminer la classe dun objet ; b dobtenir des informations concernant des modificateurs, des champs, des mthodes, des constructeurs et des superclasses ; b de retrouver les dclarations de constantes et de mthodes appartenant une interface ; b de crer une instance dune classe dont le nom nest pas connu jusqu lexcution ; b de retrouver et de dfinir la valeur dun champ dobjet ; b dinvoquer une mthode sur un objet ; b de crer un nouveau tableau, dont la taille et le type de composant sont inconnus jusquau moment de lexcution. LAPI Java Reflection est couramment utilise pour crer des outils de dveloppement tels que des dbogueurs, des navigateurs de classes et des gnrateurs dinterfaces utilisateur graphiques. Ces types doutils requirent souvent dinteragir avec des classes, des objets, des mthodes et des champs sans que lon puisse savoir lesquels ds la compilation. Lapplication doit alors retrouver ces lments en cours dexcution et y accder de manire dynamique.

Obtenir un objet Class


MyClass a = new MyClass(); a.getClass();

Lopration la plus simple en programmation rflexive consiste obtenir un objet Class. Une fois linstance

Obtenir un objet Class

181

dobjet Class rcupre, il est ensuite possible dobtenir toutes sortes dinformations concernant la classe et mme de la manipuler. Dans cet exemple, nous utilisons la mthode getClass() pour obtenir un objet Class. Cette mthode est souvent utile avec une instance dobjet dont vous ne connaissez pas la classe de provenance. Plusieurs autres approches permettent dobtenir un objet
Class. Dans le cas dune classe dont le nom de type est

connu la compilation, il existe un moyen plus simple dobtenir une instance de classe. Vous devez simplement utiliser le mot-cl de compilateur .class, comme ceci : Class aclass = String.class; Si le nom de la classe nest pas connu la compilation et se trouve seulement disponible lexcution, vous devez utiliser la mthode forName() pour obtenir un objet Class. Par exemple, la ligne de code suivante cre un objet Class associ la classe java.lang.Thread : Class c = Class.forName("java.lang.Thread"); Vous pouvez aussi utiliser la mthode getSuperClass() sur un objet Class afin dobtenir un objet Class reprsentant la superclasse de la classe rflchie. Par exemple, dans le code suivant, lobjet Class a rflchit la classe TextField et lobjet Class b rflchit la classe TextComponent car TextComponent est la superclasse de TextField : TextField textField = new TextField(); Class a = textField.getClass(); Class b = a.getSuperclass();

182 CHAPITRE 16 Programmation dynamique par rflexion

Obtenir un nom de classe


Class c = someObject.getClass(); String s = c.getName();

Pour obtenir le nom dun objet Class, il suffit dappeler la mthode getName() sur lobjet concern. Lobjet String retourn par la mthode getName() est un nom de classe pleinement qualifi. Dans cet exemple, si la variable someObject est une instance de la classe String, le nom retourn par lappel getName() est : java.lang.String.

Dcouvrir des modicateurs de classe


Class c = someObject.getClass(); int mods = c.getModifiers(); if (Modifier.isPublic(mods)) System.out.println("public"); if (Modifier.isAbstract(mods)) System.out.println("abstract"); if (Modifier.isFinal(mods)) System.out.println("final");

Dans les dfinitions de classe, plusieurs mots-cls appels modificateurs peuvent prcder le mot-cl class. Ces modificateurs sont public, abstract ou final. Pour dcouvrir quel modificateur a t appliqu une classe, vous devez dabord obtenir un objet Class reprsentant la classe concerne avec la mthode getClass(). Ensuite, vous devez appeler la mthode getModifiers() sur lobjet de

Trouver des superclasses

183

classe pour rcuprer une valeur int code reprsentant les modificateurs. Les mthodes statiques de la classe java.lang.reflect.Modifier peuvent ensuite tre utilises pour dterminer les modificateurs qui ont t appliqus. Ces mthodes statiques sont isPublic(), isAbstract() et isFinal().
Info Si lun de vos objets de classe peut reprsenter une interface, il peut aussi tre souhaitable dutiliser la mthode isInterface(). Cette mthode retourne true si les modificateurs passs incluent le modificateur interface. La classe Modifier contient des mthodes statiques supplmentaires qui permettent de dterminer quels modificateurs ont t appliqus aux mthodes et variables de la classe, dont les suivantes : isPrivate(), isProtected(), isStatic(), isSynchronized(), isVolatile(), isTransient(), isNative() et isStrict().

Trouver des superclasses


Class cls = obj.getClass(); Class superclass = cls.getSuperclass();

Les anctres dune classe sont appels ses superclasses. Elles peuvent tre retrouves par rflexion. Une fois que vous avez obtenu un objet Class, vous pouvez utiliser la mthode getSuperclass() pour retrouver la superclasse de la classe. Si la superclasse existe, un objet Class est retourn. Sil ny a pas de superclasse, la mthode retourne null. Rappelez-vous que le Java ne supporte que lhritage unique : chaque classe ne peut donc avoir quune seule superclasse.

184 CHAPITRE 16 Programmation dynamique par rflexion

Plus prcisment, chaque classe ne peut avoir quune seule superclasse directe. En thorie, toutes les classes anctres sont considres tre des superclasses. Pour les rcuprer toutes, vous devez rcursivement appeler la mthode getSuperclass() sur chacun des objets Class retourns. La mthode suivante imprime toutes les superclasses associes lobjet pass : static void printSuperclasses(Object obj) { Class cls = obj.getClass(); Class superclass = cls.getSuperclass(); while (superclass != null) { String className = superclass.getName(); System.out.println(className); cls = superclass; superclass = cls.getSuperclass(); } } Les EDI (environnements de dveloppement intgr) comme Eclipse incluent souvent un navigateur de classes qui permet au dveloppeur de parcourir visuellement la hirarchie des classes. La technique que nous venons de prsenter est gnralement utilise pour construire ces navigateurs de classes. Pour dvelopper un navigateur de classes visuel, votre application doit pouvoir retrouver les superclasses dune classe donne.

Dterminer les interfaces implmentes par une classe

185

Dterminer les interfaces implmentes par une classe


Class c = someObject.getClass(); Class[] interfaces = c.getInterfaces(); for (int i = 0; i < interfaces.length; i++) { String interfaceName = interfaces[i].getName(); System.out.println(interfaceName); }

Dans lexemple prcdent, nous avons vu comment retrouver les superclasses associes une classe donne. Ces superclasses sont lies au mcanisme dhritage et dextension des classes du Java. En plus des possibilits qui vous sont offertes en matire dextension des classes, le Java vous permet galement dimplmenter des interfaces. Les interfaces quune classe donne a implmentes peuvent aussi tre retrouves par rflexion. Une fois que vous avez obtenu un objet Class, vous devez utiliser la mthode getInterfaces() pour rcuprer les interfaces implmentes par la classe. getInterfaces() retourne un tableau dobjets Class. Chaque objet du tableau reprsente une interface implmente par la classe concerne. Vous pouvez utiliser la mthode getName() de ces objets Class pour rcuprer le nom des interfaces implmentes.

186 CHAPITRE 16 Programmation dynamique par rflexion

Dcouvrir des champs de classe


Class c = someObject.getClass(); Field[] publicFields = c.getFields(); for (int i = 0; i < publicFields.length; i++) { String fieldName = publicFields[i].getName(); Class fieldType = publicFields[i].getType(); String fieldTypeStr = fieldType.getName(); System.out.println("Name: " + fieldName); System.out.println("Type: " + fieldTypeStr); }

Les champs publics dune classe peuvent tre dcouverts laide de la mthode getFields() de lobjet Class. La mthode getFields() retourne un tableau dobjets Field contenant un objet par champ public accessible. Les champs publics accessibles retourns ne sont pas ncessairement des champs contenus directement dans la classe avec laquelle vous travaillez. Il peut aussi sagir des champs contenus : b dans une superclasse ; b dans une interface implmente ; b dans une interface tendue partir dune interface implmente par la classe. A laide de la classe Field, vous pouvez rcuprer le nom, le type et les modificateurs du champ. Ici, nous imprimons le nom et le type de chacun des champs. Vous pouvez galement retrouver et dfinir la valeur des champs. Pour plus de dtails ce sujet, consultez les exemples "Rcuprer des valeurs de champ" et "Dfinir des valeurs de champ" de ce chapitre. Si vous le prfrez, vous pouvez aussi rcuprer un champ individuel dun objet au lieu de tous ses champs si vous en

Dcouvrir des constructeurs de classe

187

connaissez le nom. Lexemple suivant montre comment rcuprer un champ unique : Class c = someObject.getClass(); Field titleField = c.getField("title"); Ce code rcupre un objet Field reprsentant le champ nomm "title". Les mthodes getFields() et getField() ne retournent que les membres de donnes publics. Si vous souhaitez rcuprer tous les champs dune classe et notamment ses champs privs et protgs, utilisez les mthodes getDeclaredFields() ou getDeclaredField(). Elles se comportent comme leurs quivalents getFields() et getField() mais retournent tous les champs en incluant les champs privs et protgs.

Dcouvrir des constructeurs de classe


Class c = someObject.getClass(); Constructor[] constructors = c.getConstructors(); for (int i = 0; i < constructors.length; i++) { Class[] paramTypes = constructors[i].getParameterTypes(); for (int k = 0; k < paramTypes.length; k ++) { String paramTypeStr = paramTypes[k].getName(); System.out.print(paramTypeStr + " "); } System.out.println(); }

La mthode getConstructors() peut tre appele sur un objet Class afin de rcuprer des informations concernant les constructeurs publics dune classe. Elle retourne un

188 CHAPITRE 16 Programmation dynamique par rflexion

tableau dobjets Constructor, qui peuvent ensuite tre utiliss pour retrouver le nom, les modificateurs et les types de paramtre des constructeurs et les exceptions qui peuvent tre leves. Lobjet Constructor possde galement une mthode newInstance() permettant de crer une nouvelle instance de la classe du constructeur. Dans cet exemple, nous obtenons tous les constructeurs de la classe someObject. Pour chaque constructeur trouv, nous rcuprons un tableau dobjets Class reprsentant tous ses paramtres. A la fin, nous imprimons chacun des types de paramtre pour chaque constructeur.
Info Le premier constructeur contenu dans le tableau de constructeurs retourn est toujours le constructeur sans argument par dfaut lorsque ce dernier existe. Sil nexiste pas, le constructeur sans argument est dfini par dfaut.

Vous pouvez aussi retrouver directement un constructeur public individuel au lieu de rcuprer tous les constructeurs dun objet pour peu que vous connaissiez les types de ses paramtres. Lexemple suivant montre comment procder : Class c = someObject.getClass(); Class[] paramTypes = new Class[] {String.class}; Constructor aCnstrct = c.getConstructor(paramTypes); Nous obtenons un objet Constructor reprsentant le constructeur qui prend un unique paramtre String. Les mthodes getConstructors() et getConstructor() ne retournent que les constructeurs publics. Si vous souhaitez retrouver tous les constructeurs dune classe et notamment ses constructeurs privs, vous devez utiliser les mthodes getDeclaredConstructors() ou getDeclaredConstructor().

Dcouvrir des informations de mthode

189

Celles-ci se comportent comme leurs quivalents getConstructors() et getConstructor() mais retournent tous les constructeurs en incluant les constructeurs privs.

Dcouvrir des informations de mthode


Class c = someObject.getClass(); Method[] methods = c.getMethods(); for (int i = 0; i < methods.length; i++) { String methodName = methods[i].getName(); System.out.println("Name: " + methodName); String returnType = methods[i].getReturnType().getName(); System.out.println("Return Type: " + returnType); Class[] paramTypes = methods[i].getParameterTypes(); System.out.print("Parameter Types:"); for (int k = 0; k < paramTypes.length; k ++) { String paramTypeStr = paramTypes[k].getName(); System.out.print(" " + paramTypeStr); } System.out.println(); }

La mthode getMethods() peut tre appele sur un objet Class afin de rcuprer des informations concernant les mthodes publiques dune classe. Elle retourne un tableau dobjets Method, qui peuvent ensuite tre utiliss pour retrouver le nom, le type de retour, les types de paramtres, les modificateurs de la classe et les exceptions qui peuvent tre leves. La mthode Method.invoke() peut galement tre utilise pour appeler la mthode. Pour plus dinformations sur linvocation des mthodes, consultez lexemple "Invoquer des mthodes" de ce chapitre.

190 CHAPITRE 16 Programmation dynamique par rflexion

Dans lexemple prcdent, une fois que nous rcuprons le tableau de mthodes, nous le parcourons en boucle pour imprimer le nom, le type de retour et une liste des types de paramtres de chacune des mthodes. Vous pouvez aussi retrouver une mthode publique individuelle au lieu de rcuprer toutes les mthodes dun objet, pourvu que vous connaissiez son nom et les types de ses paramtres. Lexemple suivant montre comment procder : Class c = someObject.getClass(); Class[] paramTypes = new Class[] {String.class, Integer.class}; Method meth = c.getMethod("setValues", paramTypes); Dans cet exemple, nous obtenons un objet Method reprsentant la mthode nomme setValue qui prend deux paramtres de type String et Integer. Les mthodes getMethods() et getMethod() dont nous venons de traiter retournent lensemble des mthodes publiques auxquelles il est possible daccder avec une classe. Des mthodes quivalentes appeles getDeclaredMethods() et getDeclaredMethod() permettent dobtenir toutes les mthodes quel que soit leur type daccs. Elles se comportent exactement de la mme manire mais retournent toutes les mthodes de la classe concerne indpendamment de leur type daccs. Il est ainsi possible dobtenir les mthodes prives galement. Les EDI (environnements de dveloppement intgr) comme Eclipse incluent souvent un navigateur de classes qui permet au dveloppeur de parcourir visuellement la hirarchie des classes. La technique que nous venons de prsenter est gnralement utilise pour construire ces navigateurs de classes. Pour dvelopper un navigateur de classes visuel, votre application doit avoir un moyen de connatre toutes les mthodes dune classe donne.

Retrouver des valeurs de champ

191

Retrouver des valeurs de champ


Class c = anObject.getClass(); Field titleField = c.getField("title"); String titleVal = (String) titleField.get(anObject);

Pour retrouver une valeur de champ, vous devez commencer par rcuprer un objet Field pour le champ dont vous souhaitez connatre la valeur. Pour plus dinformations sur lobtention des objets Field dune classe, consultez lexemple "Dcouvrir des champs de classe" prcdemment dans ce chapitre. La classe Field propose des mthodes spcialises pour rcuprer les valeurs des types primitifs, dont getInt(), getFloat() et getByte(). Pour plus de dtails sur les mthodes getter de lobjet Field, consultez la JavaDoc (en anglais) ladresse suivante : http://java.sun.com/ j2se/1.5.0/docs/api/java/lang/reflect/Field.html. Pour retrouver des champs stocks sous forme dobjets et non comme des primitifs, vous devez utiliser la mthode plus gnrale get() et transtyper le rsultat de retour sur le type dobjet appropri. Dans cet exemple, nous obtenons le champ nomm "title". Aprs avoir rcupr le champ sous forme dobjet Field, nous obtenons ensuite la valeur du champ en utilisant la mthode get() et en transtypant le rsultat en type String. Dans cet exemple, nous connaissions le nom du champ dont nous souhaitions retrouver la valeur. Cette valeur pourrait cependant tre obtenue sans mme connatre son nom la compilation, en combinant cet exemple avec lexemple "Dcouvrir des champs de classe" o nous avons montr comment obtenir des noms de champs. Cette technique pourrait par exemple tre utile dans un outil de gnrateur dinterface utilisateur graphique qui

192 CHAPITRE 16 Programmation dynamique par rflexion

ncessiterait dobtenir la valeur de diffrents champs dobjets de linterface dont les noms ne seraient pas connus avant lexcution.

Dnir des valeurs de champ


String newTitle = "President"; Class c = someObject.getClass(); Field titleField = c.getField("title"); titleField.set(someObject, newTitle);

Pour dfinir une valeur de champ, vous devez dabord obtenir un objet Field pour le champ dont vous souhaitez dfinir la valeur. Pour plus dinformations sur lobtention dobjets Field partir dune classe, consultez lexemple "Dcouvrir des champs de classe" prcdemment dans ce chapitre. Rfrez-vous aussi lexemple "Retrouver des valeurs de champ" pour plus dinformations sur lobtention des valeurs de champ. La classe Field possde des mthodes spcialises pour dfinir les valeurs des types primitifs, dont setInt(), setFloat() et setByte(). Pour plus de dtails sur les mthodes set disponibles pour lobjet Field, consultez la JavaDoc (en anglais) ladresse : http://java.sun.com/j2se/1.5.0/ docs/api/java/lang/reflect/Field.html. Pour positionner des champs stocks sous forme dobjets et non sous forme de types primitifs, vous devez utiliser la mthode set() plus gnrale en passant linstance dobjet dont vous dfinissez les valeurs de champ et la valeur de champ comme objet. Dans cet exemple, nous positionnons le champ nomm "title". Aprs avoir obtenu le champ sous forme dobjet Field, nous dfinissons sa valeur avec set(), en passant linstance dobjet dont nous positionnons les valeurs de champ et la nouvelle valeur pour la chane de titre.

Invoquer des mthodes

193

Pour cet exemple, nous connaissions le nom du champ dont nous souhaitions dfinir la valeur. Il est cependant possible de dfinir la valeur des champs dont vous ne connaissez pas le nom la compilation, en combinant lapproche de cet exemple avec celle de lexemple "Dcouvrir des champs de classe" prcdemment dans ce chapitre. Cette technique peut par exemple tre utile pour un gnrateur dinterface utilisateur graphique avec lequel vous devez positionner la valeur de diffrents champs dobjet dinterface utilisateur graphique dont les noms ne peuvent tre connus avant lexcution. Les dbogueurs vous permettent souvent de modifier la valeur dun champ au cours dune session de dbogage. Pour implmenter ce type de fonctionnalit, le dveloppeur du programme peut utiliser la technique de cet exemple afin de positionner la valeur des champs car il ne peut connatre la compilation le champ dont vous souhaiterez positionner la valeur lexcution.

Invoquer des mthodes


Baseball bbObj = new Baseball(); Class c = Baseball.class; Class[] paramTypes = new Class[] {int.class, int.class}; Method calcMeth = c.getMethod("calcBatAvg", paramTypes); Object[] args = new Object[] {new Integer(30), new Integer(100)}; Float result = (Float) calcMeth.invoke(bbObj, args);

LAPI Reflection permet dinvoquer de manire dynamique des mthodes dont vous ne connaissez pas le nom la compilation. Vous devez dabord obtenir un objet Method pour la mthode invoquer. Pour plus dinformations sur lobtention des objets Method partir dune

194 CHAPITRE 16 Programmation dynamique par rflexion

classe, consultez lexemple "Dcouvrir des informations de mthode" prcdemment dans ce chapitre. Dans lexemple prcdent, nous tentons dinvoquer une mthode qui calcule une moyenne de russite en baseball. La mthode nomme calcBatAvg() prend deux paramtres entiers, un compte des coups russis et un compte des "prsences la batte" (at-bats). La mthode retourne une moyenne la batte sous forme dobjet Float. Pour linvoquer, nous suivons ces tapes : b Nous obtenons un objet Method associ la mthode calcBatAvg() de lobjet Class qui reprsente la classe Baseball. b Nous invoquons la mthode calcBatAvg() en utilisant la mthode invoke() de lobjet Method. La mthode invoke() prend deux paramtres : un objet dont la classe dclare ou hrite la mthode et un tableau de valeurs de paramtre passer la mthode invoque. Si la mthode est statique, le premier paramtre est ignor et peut valoir null. Si la mthode ne prend aucun paramtre, le tableau darguments peut tre de longueur nulle ou valoir null. Dans notre exemple, nous passons une instance de lobjet Baseball comme premier paramtre la mthode invoke() et un tableau dobjets contenant deux valeurs entires encapsules en second paramtre. La valeur de retour de la mthode invoke() correspond la valeur retourne par la mthode invoque soit ici, la valeur de retour de calcBatAvg(). Si la mthode retourne un primitif, la valeur est dabord encapsule dans un objet et retourne sous forme dobjet. Si la mthode possde le type de retour void, la valeur null est retourne. La mthode calcBatAvg() retourne une valeur Float. Nous transtypons donc lobjet retourn afin den faire un objet Float.

Charger et instancier une classe de manire dynamique

195

Cette technique pourrait tre utile pour limplmentation dun dbogueur permettant lutilisateur de slectionner une mthode et de linvoquer. La mthode slectionne ne pouvant tre connue avant lexcution, elle peut tre retrouve de manire rflexive puis invoque au moyen de cette technique.

Charger et instancier une classe de manire dynamique


Class personClass = Class.forName(personClassName); Object personObject = personClass.newInstance(); Person person = (Person)personObject;

Les mthodes Class.forName() et newInstance() de lobjet Class permettent de charger et dinstancier dynamiquement une classe dont vous ne connaissez pas le nom jusqu lexcution. Dans cet exemple, nous chargeons notre classe en utilisant la mthode Class.forName() laquelle nous passons le nom de la classe charger. forName() retourne un objet Class. Nous appelons ensuite la mthode newInstance() sur lobjet Class pour instancier une instance de la classe. La mthode newInstance() retourne un type Object gnral que nous transtypons dans le type attendu. Cette technique peut tre particulirement utile si vous avez une classe qui tend une classe de base ou implmente une interface et que vous souhaitez stocker le nom de la classe dextension ou dimplmentation dans un fichier de configuration. Lutilisateur final peut alors ajouter de manire dynamique diffrentes implmentations sans devoir recompiler lapplication. Par exemple, si notre

196 CHAPITRE 16 Programmation dynamique par rflexion

application incluait le code dexemple prcdent et dans un plug-in, le code suivant, nous pourrions lamener instancier dynamiquement un objet BusinessPerson lexcution en spcifiant le nom de classe complet de lobjet BusinessPerson dans un fichier de configuration. Avant dexcuter notre exemple, nous lirions le nom de classe depuis le fichier de configuration et attribuerions cette valeur la variable personClassName. public class BusinessPerson extends Person { //Corps de la classe, tends le comportement de la classe Person } Le code de lapplication ninclurait ainsi aucune rfrence la classe BusinessPerson elle-mme. Il ne serait donc ncessaire de coder en dur que la classe de base ou linterface gnrique, limplmentation spcifique pouvant tre configure de manire dynamique lexcution en ditant le fichier de configuration.

17
Empaquetage et documentation des classes
Les applications Java sont gnralement constitues de nombreuses classes et peuvent parfois mme en compter des centaines ou des milliers. Puisque le Java requiert que chaque classe publique soit dfinie dans un fichier spar, vous aurez au moins autant de fichiers que vous avez de classes. Ce foisonnement peut rapidement devenir ingrable lorsquil sagit de travailler avec des classes, de retrouver des fichiers ou dinstaller et de distribuer une application. Ce problme a heureusement t anticip ds la cration du Java. Sun a dfini un mcanisme dempaquetage standard permettant de placer les classes lies dans des paquetages. Les paquetages utiliss en Java permettent dorganiser les classes daprs leurs fonctionnalits. Le mcanisme dempaquetage organise galement les fichiers source Java en une structure de rpertoires connue dfinie par rapport aux noms des paquetages utiliss.

198 CHAPITRE 17 Empaquetage et documentation des classes

Un mcanisme standard en Java est aussi propos pour empaqueter les classes Java en fichiers darchive standard. Les applications peuvent tre excutes directement depuis le fichier darchive et des bibliothques distribues sous forme darchive. Le fichier darchive Java standard est le fichier JAR, qui possde lextension .jar. Il utilise le protocole darchivage ZIP. Les fichiers JAR peuvent tre extraits en utilisant nimporte quel outil prenant en charge la dcompression des archives ZIP. Sun propose galement loutil jar pour crer et dcompresser des archives JAR. Celui-ci fait partie de la distribution JDK standard. JAR est lacronyme de Java Archive.

Crer un paquetage
package com.timothyfisher.book;

Dans les applications ou les bibliothques de grande taille, les classes Java sorganisent gnralement sous forme de paquetages. Pour placer une classe dans un paquetage, il vous suffit dinclure une instruction package au dbut du fichier de classe, comme le montre lexemple prcdent. Linstruction package doit correspondre la premire ligne non commente du fichier de classe. Dans notre exemple, nous attribuons la classe contenue dans le fichier o linstruction figure au paquetage com.timothyfisher.book. Le nom du paquetage de la classe fait partie de son nom complet. Si nous crons une classe nomme MathBook dans le paquetage com.timothyfisher.book, le nom complet de la classe est alors com.timothyfisher.book.MathBook. Les noms de paquetage rgissent galement la structure des rpertoires dans lesquels les fichiers source

Crer un paquetage

199

des classes sont stocks. Chaque lment du nom de chemin reprsente un rpertoire. Par exemple, si votre rpertoire racine du code source est project/src, le code source pour la classe MathBook est stock dans le rpertoire suivant : project/src/com/timothyfisher/book/ Les bibliothques Java standard sont toutes organises dans des paquetages avec lesquels vous devez tre familiaris. Parmi les exemples de paquetages, on peut citer java.io, java.lang ou bien encore java.util. Les classes stockes dans un paquetage peuvent aussi tre importes facilement dans un fichier. Vous pouvez ainsi importer un paquetage entier dans votre fichier source Java avec la syntaxe suivante : import java.util.*; Cette instruction import importe toutes les classes contenues dans le paquetage java.util. Notez cependant quelle nimporte pas les classes contenues dans les souspaquetages de java.util, comme celles contenues dans le paquetage java.util.logging. Une instruction import spare est requise pour limportation de ces classes. Le Java 5.0 a introduit une nouvelle fonctionnalit lie limportation des classes appele importations statiques. Les importations statiques permettent dimporter des membres statiques de classes en leur permettant dtre utiliss sans qualification de classe. Par exemple, pour rfrencer la mthode cos() dans le paquetage java.lang.Math, vous pourrez vous y rfrer de la manire suivante : double val = Math.cos(90);

200 CHAPITRE 17 Empaquetage et documentation des classes

Pour cela, vous devrez importer le paquetage java.lang .Math laide dune importation statique, comme ceci :
import static java.lang.Math.*;

Vous pouvez faire rfrence la mthode cos() de la manire suivante : double val = cos(90); Lors de lexcution dune application Java depuis la ligne de commande avec lexcutable java, vous devez inclure le nom de paquetage complet lorsque vous spcifiez la classe excutable principale. Par exemple, pour excuter une mthode main() dans lexemple MathBook signal prcdemment, vous devrez taper ceci : java com.timothyfisher.book.MathBook Cette commande est excute depuis la racine de la structure du paquetage ici, le rpertoire parent du rpertoire com. Les classes qui ne sont pas spcifiquement attribues un paquetage avec une instruction package sont considres tres incluses dans un paquetage "par dfaut". Le bon usage exige que vous placiez toujours vos classes dans des paquetages dfinis par vos soins. Les classes qui se trouvent dans le paquetage par dfaut ne peuvent pas tre importes ni utilises lintrieur des classes des autres paquetages.

Documenter des classes avec JavaDoc


javadoc -d \home\html -sourcepath \home\src -subpackages java.net

Documenter des classes avec JavaDoc

201

JavaDoc est un outil permettant de gnrer de la documentation dAPI au format HTML partir de commentaires placs dans les fichiers de code source Java. Loutil JavaDoc fait partie intgrante de linstallation standard du JDK. Lexemple prsent ici illustre un type dusage particulier de loutil JavaDoc. JavaDoc possde de nombreuses options et de nombreux drapeaux en ligne de commande qui peuvent tre utiliss pour documenter des classes et des paquetages. Pour obtenir une description complte des options de JavaDoc, consultez la documentation de Sun (en anglais) ladresse http://java.sun.com/j2se/1.5.0/ docs/guide/javadoc/index.html. La commande javadoc utilise dans cet exemple gnre une documentation JavaDoc pour toutes les classes contenues dans le paquetage java.net et tous ses sous-paquetages. Le code source doit se trouver dans le rpertoire \home\src directory. La sortie de la commande est crite dans le rpertoire \home\html. Voici un exemple classique de commentaire JavaDoc dans un fichier source Java : /** * Un commentaire dcrivant une classe ou une mthode * * Les balises spciales sont prcdes par le caractre @ * pour documenter les paramtres de mthode, types de * retour, nom dauteur de mthode ou de classe, etc. Voici * un exemple de paramtre document. * @param input Les donnes dentre pour cette mthode. */

202 CHAPITRE 17 Empaquetage et documentation des classes

Les squences de caractres /** et */ signalent le dbut et la fin dun commentaire JavaDoc. Loutil JavaDoc produit une sortie analogue la documentation de classe Java standard que vous aurez invitablement rencontre si vous avez consult des documents Java en ligne par le pass. Le JDK est lui-mme document avec la documentation JavaDoc. Pour visualiser la JavaDoc du JDK, rendez-vous ladresse suivante : http://java.sun .com/j2se/1.5.0/docs/api/index.html. La documentation gnre par JavaDoc permet de parcourir facilement les classes qui composent une application ou une bibliothque. Une page dindex propose une liste de toutes les classes et des liens hypertexte vers chacune dentre elles. Des index sont galement fournis pour chaque paquetage. La cration de la documentation JavaDoc sintgre souvent au processus de gnration des applications. Si vous utilisez loutil de compilation Ant, il existe ainsi une tche Ant permettant de gnrer la JavaDoc dans le cadre de votre processus de gnration et de compilation. La technologie qui permet JavaDoc de fonctionner a galement t utilise il y a peu pour crer dautres outils dont les fonctionnalits sortent du simple cadre de la documentation des fichiers Java. LAPI Doclet est ainsi utilise par JavaDoc et des outils tiers. Lun de ces outils tiers, parmi les plus populaires, est le projet open source XDoclet. XDoclet est un moteur servant la programmation oriente attribut. Il permet dajouter des mtadonnes votre code source afin dautomatiser des tches telles que la cration dEJB. Pour plus dinformations sur XDoclet, consultez le site http://xdoclet.sourceforge.net/.

Archiver des classes avec Jar

203

LAPI Taglet est une autre API utile pour le travail avec les commentaires de style JavaDoc qui fait partie du Java standard. Elle permet de crer des programmes appels Taglets qui peuvent modifier et formater des commentaires de style JavaDoc contenus dans vos fichiers source. Pour plus dinformations sur les Taglets, rendez-vous ladresse http://java .sun.com/j2se/1.4.2/docs/tooldocs/javadoc/taglet/ overview.html.

Archiver des classes avec Jar


jar cf project.jar *.class

Lutilitaire jar est inclus dans le JDK. Il permet dempaqueter des groupes de classes en un lot et de crer, mettre jour, extraire, lister et indexer des fichiers JAR. Avec linstruction de cet exemple, toutes les classes contenues dans le rpertoire courant depuis lequel la commande jar est excute sont places dans un fichier JAR nomm project.jar. Loption c demande lutilitaire jar de crer un nouveau fichier darchive. Loption f est toujours suivie par un nom de fichier spcifiant le nom du fichier JAR utiliser. Des applications compltes peuvent tre distribues sous forme de fichiers JAR. Elles peuvent galement tre excutes depuis le fichier JAR sans avoir les extraire au pralable. Pour plus dinformations ce sujet, consultez lexemple "Excuter un programme depuis un fichier JAR" de ce chapitre. Toutes les classes contenues dans un fichier JAR peuvent aisment tre incluses dans le CLASSPATH lors de lexcution

204 CHAPITRE 17 Empaquetage et documentation des classes

ou de la compilation dune application ou dune bibliothque Java. Pour inclure le contenu dun fichier JAR dans le CLASSPATH, incluez le chemin complet au fichier JAR au lieu du seul rpertoire. Par exemple, linstruction CLASSPATH pourrait ressembler ceci : CLASSPATH=.;c:\projects\fisher.jar;c:\projects\classes Cette instruction inclut toutes les classes contenues dans larchive fisher.jar dans le CLASSPATH. Notez bien que pour inclure les classes dans un fichier JAR, vous devez spcifier le nom du fichier JAR dans le chemin de classe. Il ne suffit pas de pointer vers un rpertoire contenant plusieurs fichiers JAR comme il est possible de le faire avec les fichiers .class. Pour plus dinformations sur lutilisation de loutil jar, consultez la documentation JAR officielle sur le site de Sun ladresse http://java.sun.com/j2se/1.5.0/docs/ guide/jar/index.html.

Excuter un programme partir dun chier JAR


java jar Scorebook.jar

Lexcutable en ligne de commande java permet dexcuter une application Java empaquete dans un fichier JAR. Pour cela, vous devez utiliser le commutateur jar lexcution de la commande java. Vous devez aussi spcifier le nom du fichier JAR contenant lapplication excuter. La classe contenant la mthode main() que vous souhaitez excuter doit tre dclare dans un fichier de manifeste.

Excuter un programme partir dun fichier JAR

205

Par exemple, pour excuter la classe com.timothyfisher.Scorebook, vous pourriez utiliser un fichier de manifeste dont le contenu serait le suivant :
Manifest-Version: 1.2 Main-Class: com.timothyfisher.Scorebook Created-By: 1.4 (Sun Microsystems Inc.)

Ce fichier de manifeste devrait alors tre plac dans le fichier JAR avec vos classes. Cette fonctionnalit permet aux dveloppeurs Java de distribuer une application dans un unique fichier JAR et dinclure un fichier de script comme un fichier BAT Windows ou un script de shell UNIX qui peuvent tre utiliss pour lancer lapplication laide dune instruction analogue celle prsente dans cet exemple.

Index
A
abs() 70 abstract 182 accept() 104, 122 add() 48 adjust() 172 Ant 7 Apache Ant 7 Jakarta RegExp 56 Log4J 81 Tomcat 129 API DocumentBuilder 157 DOM 162 JavaMail 131 JAXP 154 JDBC 141 JDOM 162 Reflection 180 SAX 155 Taglet 203 append() 24 appendChild() 162 appendReplacement() 62 appendTail() 62 Archives JAR 89, 198, 203, 204 ZIP 89, 91, 198 arraycopy() 32 ArrayList 32, 36, 38 Arrays 36 Arrondissement 71 Attributs de fichier 97 Element 162 XML 155

B
Bases de donnes JDBC 142 jeux de rsultats 148 BCC 134 before() 51 binarySearch() 38 Boolean 68 Boucles 33 for 22 parcours de collections 34 while 24, 91, 169 BufferedInputStream 113 BufferedOutputStream 115 BufferedReader 64, 80, 86, 111, 128 BufferedWriter 86 Byte 67 Bytecode 5

208

Calendar

C
Calendar 42, 84 conversion avec Date 42 proprits 51 CallableStatement 149 Caractres casse 25, 59 expressions rgulires 57 nouvelle ligne 65 CASE_INSENSITIVE 59 catch 69, 110 CC 134 Chanes 17 comparer 18 convertir la casse 25 date 44 expressions rgulires 55 parser en dates 47 rechercher 21 remplacer 61 renverser 23 retrouver une portion 58 spares par des virgules 27 tokenizer 28 validit comme nombre 68 Champs 186 retrouver des valeurs 191 Character 68 characters() 156 charAt() 22 checkAccept() 122 Chemins de classe 9, 203 relatifs et absolus 101 Class 181, 189, 195 Classes 14 ArrayList 32, 36, 38

Arrays 36 BufferedInputStream 113 BufferedOutputStream 115 BufferedReader 64 Calendar 42, 84 champs 186 chargement dynamique 195 Class 181 Collections 37 Comparator 36 Connection 144 DataInputStream 113 DataOutputStream 115 Date 42 dcouvrir des constructeurs 187 DefaultHandler 155 Document 157 documentation 197 DocumentBuilder 157 DocumentBuilderFactory 157 empaquetage 197 File 94 FilenameFilter 104 Folder 139 Formatter 82 Handler 126 HashMap 35, 40 HttpURLConnection 118, 119 InetAddress 109 instanciation dynamique 195 interfaces implmentes 185 InternetAddress 133 IOException 79 Iterator 34 Matcher 56 Math 67, 71, 75, 77 MimeBodyPart 135 MimeMessage 134 MimeMultiPart 135

INDEX

currentTimeMillis()

209

modificateurs 182 MultiPart 135 Object 35 ObjectInputStream 116 OutputStream 73 OutputStreamWriter 124 PrintStream 73 PrintWriter 112 Properties 133 Random 75 RandomAccessFile 89 regPat 58 Scanner 25 ServerSocket 122 SimpleDateFormat 44 Socket 108 Stack 24 String 17, 83 StringBuffer 18, 23, 24 StringBuilder 18 StringReader 23 StringTokenizer 24, 27, 56 TextComponent 181 TextField 181 Thread 126 ThreadGroup 176 TreeMap 37 TreeSet 37 trouver des superclasses 183 URL 108 ZipEntry 90 ClassesPattern 56 CLASSPATH 9, 203 close() 89, 108, 123, 144 closeEntry() 91 Code-octet_ 5 collection 34

Collections 32, 37 convertir en tableau 40 mappes 35 parcourir en boucle 33 retrouver un objet 38 stocker 36 Commandes java 8 javac 7 javadoc 201 Comparable 36 Comparaisons chanes 18 dates 51 nombres virgule flottante 69 tolrance 70 Comparator 36 compareTo() 20, 51 compareToIgnoreCase() 20 Compilation 7 compile() 58 ConnectException 110 Connection 144 Constructeurs 187 contains() 38 containsKey() 38 containsValue() 38 Content-length 129 Conversions Date et Calendar 42 nombre entier en binaire, octal et hexadcimal 75 cos() 76 createNewFile() 94 createStatement() 144 createTempFile() 94 CSV 27 currentThread() 176 currentTimeMillis() 52

INDEX

210

DataInputStream

D
DataInputStream 113 DataOutputStream 115 DataSource 144 Date 42 conversion avec Calendar 42 Date() 42 Dates 41 additions et soustractions 48 codes de format 45 comparer 51 diffrence 49 formater 44 nanosecondes 53 parser 47 valeur courante 42 DAY_OF_WEEK 51 DefaultHandler 155 DELETE 145 delete() 96 deleteOnExit() 95, 97 Devises 74 Dictionnaires 33 Document 157 Documentation 197 DateFormat 47 Formatter 73 Jakarta 56 JavaDoc 201 JDK 7 StringTokenizer 29 DocumentBuilder 157 DocumentBuilderFactory 157, 159 DOM 157

INDEX

Dossiers 93 afficher le contenu 103 crer 106 dplacer 99 renommer 95 supprimer 96 vrifier lexistence 99 Double 68 doWait 174 Drapeaux boolens 168 CASE_INSENSITIVE 59 doWait 174 JavaDoc 201 MULTILINE 65 Pattern 60 DriverManager 143 DTD 159

E
Eclipse 5, 190 Ecriture donnes binaires 114 donnes srialises 117 EDI 5, 190 EJB 108, 141 E-mails 131 envoyer 133 lire 137 MIME 135 empty() 24 endElement() 156 endsWith() 104 Ensembles 33

Flux

211

Entre BufferedInputStream 113 BufferedReader 86, 111, 128 DataInputStream 113 donnes binaires 88 donnes srialises 115 InputStream 87 lire 80 ObjectInputStream 116 System.in 80 texte 111 entries() 89 Entry 33 entrySet() 33, 40 Environnement 12 Epoque UNIX 48 equals() 18, 50, 69 equalsIgnoreCase() 18, 80 Erreurs 65 rseau 110 System.err 80 Exceptions ConnectException 110 FileNotFoundException 65 IOException 79, 110 NoRouteToHostException 110 NumberFormatException 69 SecurityException 122 SocketException 110 System.err 80 UnknownHostException 110 executeQuery() 144, 145 executeUpdate() 145 Excution 8 exists() 99 Expressions rgulires 55 caractres spciaux 57 nouvelle ligne 65 regPat 58

F
Fichiers 93 atteindre une position 89 close() 89 crer 94 dplacer 99 entries() 89 JAR 9, 198, 204 mkdirs() 106 modifier des attributs 97 ouvrir 86 RandomAccessFile 89 renommer 95 supprimer 95, 96 taille 98 temporaires 94 vrifier lexistence 99 ZIP 198 Field 191 File 94, 102 mkdir() 106 FilenameFilter 104 FileNotFoundException 65 final 182 find() 58 Float 68 flush() 112 Flux binaire 88 BufferedInputStream 113 BufferedOutputStream 115 BufferedReader 111, 128 DataInputStream 113 InputStream 87 ObjectInputStream 116 ObjectOutputStream 125 StreamSource 164

INDEX

212

Folder

System.err 80 System.in 80 System.out 80 ZipOutputStream 91 Folder 139 for 22 format() 44, 72, 83, 112 Formatage devises 74 Locale 82 nombres 72 sortie 81 spcificateurs de format 84 Formatter 82 codes 85 forName() 143, 181, 195 Frameworks Collections 32 EJB 141 JAF 132 FRANCE 82

G
getAbsoluteFile() 101 getByName() 109 getByte() 191 getClass() 181, 182 getConnection() 143, 144 getConstructor() 188 getConstructors() 187, 188 getContent() 118 getCurrencyInstance() 74 getDateInstance() 47 getDeclaredConstructor() 188 getDeclaredConstructors() 188 getDeclaredField() 187

getDeclaredFields() 187 getDeclaredMethod() 190 getDeclaredMethods() 190 getDefaultInstance() 138 getElementsByTagName() 158 getenv() 12 getField() 187 getFields() 186, 187 getFloat() 191 getHostAddress() 109, 122 getInetAddress() 122 getInputStream() 111, 113, 116, 118 getInstance() 42, 48, 51, 83 getInt() 191 getInterfaces() 185 getKey() 33 getMessage() 110 getMethod() 190 getMethods() 189, 190 getModifiers() 182 getMoreResults() 150 getName() 182, 185, 189 getNumberInstance() 72 getOutputStream() 112 getParameterTypes() 187 getParent() 176 getPort() 122 getProperties() 13 getProperty() 13 getResponseCode() 119 getReturnType() 189 getSuperclass() 181, 183 getThreadGroup() 176 getTime() 42 getValue() 33 GMT 48 group() 58

INDEX

JANUARY

213

H
Handler 126 hashCode() 36 HashMap 35 convertir en tableau 40 hasMoreElements() 89 hasMoreTokens() 24, 27 hasNext() 33, 34 Heures 41 codes de format 45 Hibernate 142 HTML 153 HTTP 107, 128 en-ttes 129 https 119 HttpURLConnection 118, 119

I
IANA 137 if 69 IMAP 132, 138 import 199 indexOf() 21, 38 InetAddress 109 InitialContext 144 InputStream 87 Instructions catch 69, 110 if 69 import 199 prpares 146 try 69 Integer 67

Interfaces CallableStatement 149 Comparable 36 dune classe 185 isInterface() 183 java.io.Externalizable 116 java.io.Serializable 116, 125 java.lang.Runnable 166 java.lang.Thread 166 Runnable 126, 166 InternetAddress 133 Inversion de chanes 23 invoke() 189 IOException 79, 110 IP 109 isAbstract() 183 isDirectory() 89, 102 isFinal() 183 isInterface() 183 isNative() 183 isPrivate() 183 isProtected() 183 isPublic() 183 isStatic() 183 isStrict() 183 isSynchronized() 183 isTransient() 183 isVolatile() 183 Iterator 34 iterator() 33, 34

INDEX

J
J2EE 108 J2SE 6 JAF 132 JANUARY 83

214

JAR

JAR 9, 198, 203, 204 lire 89 Java classes 14 servlets 129 types prdfinis 67 java 8 java.io 73, 79 java.io.Externalizable 116 java.io.Serializable 116, 125 java.lang 77, 179 java.lang.Math 67, 199 java.lang.reflect 179 java.lang.reflect.Modifier 183 java.lang.Runnable 166 java.lang.Thread 166, 181 java.net 108 java.text 72 java.util 33, 34, 37, 42, 75, 79 java.util.logging 81, 199 java.util.Properties 133 java.util.regex 56 javac 7 JavaDoc 201 JavaMail 131 javax.mail 131, 134 javax.mail.internet 135 javax.xml.transform 163 JAXP 154 JCP 162 JDBC 141, 142, 144 JdbcOdbcDriver 142 JDK 7 javac 7 versions 1.4 56, 131 1.5 35, 53, 73, 82

JDOM 162 JMS 108 JNDI 144 join() 169 Journalisation 81 JSP 129 JSSE 120

K
keySet() 33

L
Lecture donnes binaires 113 donnes srialises 115 e-mails 137 page Web 118 texte 111 length 32 length() 87, 98 LIFO 25 list 33 list() 103, 139 Listes 33 Locale 82 log() 77 log10() 77 Log4J 81 Long 67 long 87

INDEX

Mthodes

215

M
Machine virtuelle 8 Macintosh 12 main() 14 Majuscules 25 Mapping objet/relationnel 142 Matcher 56 matcher() 58 Math 71, 75, 77 fonctions trigonomtriques 76 Message 133 Method 189 Mthodes abs() 70 accept() 104, 122 add() 48 adjust() 172 append() 24 appendChild() 162 appendReplacement() 62 appendTail() 62 arraycopy() 32 before() 51 binarySearch() 38 characters() 156 charAt() 22 checkAccept() 122 close() 89, 108, 123, 144 closeEntry() 91 compareTo() 20, 51 compareToIgnoreCase() 20 compile() 58 contains() 38 containsKey() 38 containsValue() 38 cos() 76

createNewFile() 94 createStatement() 144 createTempFile() 94 currentThread() 176 currentTimeMillis() 52 Date() 42 dcouvrir par rflexion 189 delete() 96 deleteOnExit() 95, 97 empty() 24 endElement() 156 endsWith() 104 entries() 89 entrySet() 33, 40 equals 18 equals() 50, 69 equalsIgnoreCase() 18, 80 executeQuery() 144, 145 executeUpdate() 145 exists() 99 find() 58 flush() 112 format() 44, 72, 83, 112 forName() 143, 181, 195 getAbsoluteFile() 101 getByName() 109 getByte() 191 getClass() 181, 182 getConnection() 143, 144 getConstructor() 188 getConstructors() 187, 188 getContent() 118 getCurrencyInstance() 74 getDateInstance() 47 getDeclaredConstructor() 188 getDeclaredConstructors() 188 getDeclaredField() 187 getDeclaredFields() 187

INDEX

216

Mthodes

Mthodes (suite) getDeclaredMethod() 190 getDeclaredMethods() 190 getDefaultInstance() 138 getElementsByTagName() 158 getenv() 12 getField() 187 getFields() 186, 187 getFloat() 191 getHostAddress() 109, 122 getInetAddress() 122 getInputStream() 111, 113, 116, 118 getInstance() 42, 48, 51, 83 getInt() 191 getInterfaces() 185 getKey() 33 getMessage() 110 getMethod() 190 getMethods() 189, 190 getModifiers() 182 getMoreResults() 150 getName() 182, 185, 189 getNumberInstance() 72 getOutputStream() 112 getParameterTypes() 187 getParent() 176 getPort() 122 getProperties() 13 getProperty() 13 getResponseCode() 119 getReturnType() 189 getSuperclass() 181, 183 getThreadGroup() 176 getTime() 42 getValue() 33 group() 58 hashCode() 36

hasMoreElements() 89 hasMoreTokens() 24, 27 hasNext() 33, 34 indexOf() 21, 38 invoke() 189 invoquer 193 isAbstract() 183 isDirectory() 89, 102 isFinal() 183 isInterface() 183 isNative() 183 isPrivate() 183 isProtected() 183 isPublic() 183 isStatic() 183 isStrict() 183 isSynchronized() 183 isTransient() 183 isVolatile() 183 iterator() 33, 34 join() 169 keySet() 33 length() 87, 98 list() 103, 139 log() 77 log10() 77 main() 14 matcher() 58 mkdir() 106 mkdirs() 106 nanoTime() 53 newInstance() 188, 195 newTranformer() 164 next() 33, 34, 148 nextDouble() 75 nextElement() 24, 89 nextInt() 75 nextToken() 27

INDEX

Mthodes

217

Notify() 175 openConnection() 119 parse() 47, 155 parseInt() 68 pop() 24 prepareCall() 149 prepareStatement() 146 printf() 112 println 20 println() 112 printThreadInfo() 177 put() 35 putNextEntry() 91 random() 75 read() 23, 87, 88, 113 readBoolean() 114 readByte() 114 readChar() 114 readDouble() 114 readFloat() 114 readInt() 114 readLine() 80, 111 readLong() 114 readObject() 116 readShort() 114 readUnsignedByte() 113 readUnsignedShort() 114 renameTo() 95, 100 replaceAll() 61 reset() 172 resume() 175 reverse() 23 round() 71 run() 127, 166 seek() 89 send() 133 setArray() 146 setAsciiStream() 146 setBigDecimal() 146

setBinaryStream() 146 setBlob() 146 setBoolean() 146 setByte() 146 setBytes() 146 setCharacterStream() 146 setClob() 146 setContent() 136 setContentHandler() 155 setDate() 146 setDouble() 146 setFloat() 146 setInt() 146 setLastModified() 97 setLong() 146 setNull() 146 setObject() 146 setProperty() 13 setReadOnly() 97 setRef() 147 setSchema() 160 setShort() 147 setString() 147 setText() 136 setTime() 147 setTimestamp() 147 setURL() 147 setValidating() 159, 160 SimpleDateFormat() 44 sin() 76 sort() 36 split() 27 start() 126, 166 startElement() 156 stop() 169 StringBuffer() 62 substring() 22 suspend() 175 tan() 76

INDEX

218

Mthodes

Mthodes (suite) toArray() 40 toBinaryString() 75 toHexString() 75 toLowerCase() 104 toOctalString() 75 toString() 23, 42, 82 transform() 164 trim() 26 valueOf() 47 values() 33 visitGroup() 177 wait() 175 write() 114, 115, 123 writeBoolean() 115, 123 writeByte() 115, 123 writeBytes() 115, 123 writeChar() 115, 123 writeChars() 115, 123 writeDouble() 115, 123 writeFloat() 115, 123 writeInt() 115, 123 writeLong() 115, 123 writeObject() 125 writeShort() 115, 123 MIME 134 MimeBodyPart 135 MimeMessage 134 MimeMultiPart 135 Minuscules 25 mkdir() 106 mkdirs() 106 Modificateurs 182 abstract 182 final 182 public 182 MONTH 51 MULTILINE 65 MultiPart 135

N
NaN 70 nanoTime() 53 newInstance() 188, 195 newTranformer() 164 next() 33, 34, 148 nextDouble() 75 nextElement() 24, 89 nextInt() 75 nextToken() 27 Nombres 67 arrondir 71 chane valide 68 convertir en binaire, octal et hexadcimal 75 formater 72 virgule flottante 69 NoRouteToHostException 110 Notify() 175 NumberFormat 72 NumberFormatException 69

INDEX

O
Object 35 ObjectInputStream 116 ObjectOutputStream 125 Objets ArrayList 32, 36, 38 Arrays 36 Boolean 68 BufferedInputStream 113 BufferedOutputStream 115 BufferedReader 64, 80, 86, 128 BufferedWriter 86 Byte 67

OutputStreamWriter

219

Calendar 42, 84 Character 68 Class 181, 189, 195 collection 34 Collections 37 Comparator 36 DataInputStream 113 DataOutputStream 115 DataSource 144 Date 42 DocumentBuilderFactory 159 Double 68 DriverManager 143 Field 191 File 94, 102 FilenameFilter 104 Float 68 Handler 126 HashMap 35, 40 HttpURLConnection 118, 119 InitialContext 144 InputStream 87 Integer 67 InternetAddress 133 Iterator 34 list 33 Long 67 Matcher 56 Message 133 Method 189 MimeBodyPart 135 NumberFormat 72 Object 35 ObjectInputStream 116 ObjectOutputStream 125 OutputStream 73 OutputStreamWriter 124 Pattern 56 PreparedStatement 146 PrintStream 73

PrintWriter 112 Properties 133 RandomAccessFile 89 regPat 58 ResultSet 144, 145, 148 SAXParser 155 ServerSocket 122 Session 133 set 33 Short 67 SimpleDateFormat 44 Socket 108 Stack 24 Statement 144, 145 Store 138 StreamSource 164 String 17, 83 StringBuffer 18, 23, 24 StringBuilder 18 StringReader 23 StringTokenizer 24, 27, 56 System 13 Thread 126 ThreadGroup 176 TranformerFactory 164 Transformer 164 TreeMap 37 TreeSet 37 XMLReader 155 ZipEntry 90, 91 ZipOutputStream 91 openConnection() 119 Options _classpath 9 javac 7 JavaDoc 201 purge automatique 124 scurit Java 94 OutputStream 73 OutputStreamWriter 124

INDEX

220

Paquetages

P
Paquetages crer 198 Jakarta RegExp 56 java.io 73, 79 java.lang 77, 179 java.lang.Math 67, 199 java.lang.reflect 179 java.lang.reflect.Modifier 183 java.lang.Thread 181 java.net 108 java.text 72 java.util 33, 34, 37, 42, 75, 79 java.util.logging 199 java.util.regex 56 javax.mail 131, 134 javax.mail.internet 135 javax.xml.transform 163 parse() 47, 155 parseInt() 68 PATH 12 Pattern 56 proprits 59 PI 82 Piles 24 POP 107 pop() 24 POP3 132, 138 prepareCall() 149 PreparedStatement 146 prepareStatement() 146 printf() 112 println() 20, 112 PrintStream 73 printThreadInfo() 177 PrintWriter 112 Procdures stockes 149

Programmes compiler 7 excuter 8 project.jar 203 Properties 133 Proprits CASE_INSENSITIVE 59 DAY_OF_WEEK 51 Entry 33 FRANCE 82 JANUARY 83 length 32 MONTH 51 MULTILINE 65 systme 13 timezone 13 UNICODE_CASE 60 WEEK_OF_YEAR 51 YEAR 51 public 182 put() 35 putNextEntry() 91

INDEX

R
random() 75 RandomAccessFile 89 read() 23, 87, 88, 113 readBoolean() 114 readByte() 114 readChar() 114 readDouble() 114 readFloat() 114 readInt() 114 readLine() 80, 111 readLong() 114 readObject() 116 readShort() 114

setProperty()

221

readUnsignedByte() 113 readUnsignedShort() 114 Reflection 180 Rflexion 179 champs 186, 191 constructeurs 187 interfaces 185 mthodes 189 RegExp 56 Rgionalisation 82 regPat 58 renameTo() 95, 100 Rpertoires 93 afficher le contenu 103 crer 106 dplacer 99 renommer 95 supprimer 96 vrifier lexistence 99 replaceAll() 61 Rseau clients 107 erreurs 110 retrouver des adresses IP 109 reset() 172 ResultSet 144, 145, 148 resume() 175 reverse() 23 round() 71 run() 127, 166 Runnable 126, 166

S
SAX 155 SAXInputSources 157 startElement() 156 SAXInputSources 157

SAXParser 155 Scanner 25 Schmas 160 SecurityException 122 seek() 89 SELECT 144, 148 send() 133 serialVersionUID 116 ServerSocket 122 Serveurs 121 contacter 108 contenu HTTP 128 crer 122 retourner un objet 125 retourner une rponse 123 Tomcat 129 Servlets 129 Session 133 set 33 setArray() 146 setAsciiStream() 146 setBigDecimal() 146 setBinaryStream() 146 setBlob() 146 setBoolean() 146 setByte() 146 setBytes() 146 setCharacterStream() 146 setClob() 146 setContent() 136 setContentHandler() 155 setDate() 146 setDouble() 146 setFloat() 146 setInt() 146 setLastModified() 97 setNull() 146 setObject() 146 setProperty() 13

INDEX

222

setReadOnly()

setReadOnly() 97 setRef() 147 setSchema() 160 setShort() 147 setString() 147 setText() 136 setTime() 147 setTimestamp() 147 setURL() 147 setValidating() 159, 160 SGML 153 Short 67 SimpleDateFormat() 44 sin() 76 SMTP 107, 132 SocketException 110 Sockets 108, 122 exceptions 110 fermer 123 sort() 36 Sortie 112 BufferedOutputStream 115 BufferedWriter 86 donnes binaires 114 donnes srialises 117 crire 80 formater 81 ObjectOutputStream 125 System.out 80 Sous-chanes 21, 58 Spcificateurs de format 84 split() 27 SQL DELETE 145 SELECT 144, 148 UPDATE 145 SSL 119 Stack() 24 start() 126, 166

startElement() 156 Statement 144, 145 stop() 169 Store 138 StreamSource 164 String 17, 83 StringBuffer() 18, 23, 24, 62 StringBuilder 18 StringReader 23 StringTokenizer 24, 27, 56 Structures 31 substring() 22 Sun 6 Superclasses 183 suspend() 175 Synchronisation des threads 171 synchronized 171 System 13 System.err 80 System.in 80 System.out 80

INDEX

T
Tableaux crer partir dune collection 40 doctets 87 longueur 32 redimensionner 32 Taglet 203 tan() 76 TextComponent 181 Texte caractres de nouvelle ligne 65 crire 112 crire vers une sortie standard 80

writeChars()

223

java.text 72 lire 111 dans un tableau doctets 87 depuis une entre standard 80 remplacer 61 retrouver 58 TextField 181 Thread 126 ThreadGroup 176 Threads 165 arrter 168 lancer 166 lister 176 suspendre 174 synchroniser 171 timezone 13 TO 134 toArray() 40 toBinaryString() 75 toHexString() 75 Tokenizer 28 Tolrance 70 toLowerCase() 104 Tomcat 129 toOctalString() 75 toString() 23, 42, 82 TranformerFactory 164 transform() 164 Transformer 164 TreeMap 37 TreeSet 37 trim() 26 try 69

U
UNICODE_CASE 60 UNIX 48 UnknownHostException 110 UPDATE 145 URL 108

V
valueOf() 47 values() 33 Variables CLASSPATH 9 d'environnement 12 Macintosh 12 PATH 12 visitGroup() 177 void 37

INDEX

W
wait() 175 WebLogic 143 WebSphere 143 WEEK_OF_YEAR 51 while 24, 91, 169 write() 114, 115, 123 writeBoolean() 115, 123 writeByte() 115, 123 writeBytes() 115, 123 writeChar() 115, 123 writeChars() 115, 123

224

writeDouble()

writeDouble() 115, 123 writeFloat() 115, 123 writeInt() 115, 123 writeLong() 115, 123 writeObject() 125 writeShort() 115, 123

XMLReader 155 XSL 163 XSLT 163 XStream 125

Y X
YEAR 51 XBNF 160 XDoclet 202 XHTML 153 XML 153 DOM 157 DTD 159 parser avec SAX 155 schmas 160 setSchema() 160 startElement() 156 transformations XSL 164 XBNF 160

Z
ZIP 198 crer 90 lire 89 ZipEntry 90, 91 ZipOutputStream 91

INDEX

LE GUIDE DE SURVIE

Java

LESSENTIEL DU CODE ET DES COMMANDES


Ce Guide de survie vous livre tout le code dont vous avez besoin pour raliser rapidement et efcacement vos projets de dveloppement en Java.

CONCIS ET MANIABLE
Facile transporter, facile utiliser nis les livres encombrants !

PRATIQUE ET FONCTIONNEL
Plus de 100 fragments de code personnalisables pour programmer du Java fonctionnel dans toutes les situations. Timothy Fisher est un professionnel du dveloppement de logiciels Java depuis 1997. Il est actuellement consultant pour lentreprise Compuware Corporation Dtroit dans le Michigan. Il aime crire sur cette technologie et a contribu aux deux ouvrages Java Developers Journal et XML Journal. Tim est galement passionn par lducation et lutilisation des technologies Internet avances dans ce domaine.
Niveau : Intermdiaire Catgorie : Programmation Conguration : Multiplate-forme

Pearson Education France 47 bis, rue des Vinaigriers 75010 Paris Tl. : 01 72 74 90 00 Fax : 01 42 05 22 17 www.pearson.fr

ISBN : 978-2-7440-4004-7

You might also like