UKOnline

Entrée et sortie standards

À tout programme sont toujours associés trois flux de données : une sortie standard (communément appelée stdout) qui permet au programme de produire des données, une entrée standard (stdin) qui permet à l'utilisateur de fournir des données au programme et enfin une sortie d'erreur standard (stderr) qui permet de fournir des renseignements à propos d'erreurs survenues pendant l'exécution du programme.

Il est très facile de manipuler ces trois flux en Java. En effet, dans la classe System se trouvent trois objets permettant de les manipuler : out, in et err. Ce sont trois objets qui sont créés automatiquement lorsque le programme démarre, il s'agit de variables de classe. Cette section passe en revue chacun de ces trois flux.

Sortie standard

Nous avons déjà rencontré et utilisé à maintes reprises l'objet System.out qui représente la sortie standard. Il permet d'afficher des données sur la sortie standard du programme (typiquement la console) :

En consultant la documentation de la librairie standard Java, on trouve assez vite que System.out est un objet de type PrintStream. Cette classe, qui se trouve dans le package java.io, offre de nombreuses méthodes. Celles qui nous intéressent pour le moment sont reprises sur la figure 29.

Méthode Description
print Ajoute une chaine de caractères à stdout
println Ajoute une chaine de caractères suivie d'un retour à la ligne à stdout
printf Ajoute une chaine de caractères formatée à stdout (depuis Java 5)
flush Force la sortie des caractères stockés dans le tampon de stdout
Quelques méthodes de la classe PrintStream.

On a déjà rencontré et utilisé les deux premières méthodes. Celles-ci existent en plusieurs versions : il y en a qui prennent comme paramètre un int, un double, un String, etc. on reviendra là-dessus plus tard.

Quant à la méthode flush, elle permet de forcer l'écriture sur la sortie standard de tout le tampon. En effet, ce n'est pas parce qu'il y a un appel vers la méthode print ou println que le texte s'affiche tout de suite.

En fait, il existe un système de tampon qui accumule des caractères et qui ne les affiche que lorsqu'il y en a assez ou qu'un certain temps s'est écoulé. Si on doit absolument afficher tout de suite les caractères, alors il suffit d'appeler la méthode flush.

Sortie formatée

Avec les méthodes print et println, ce qu'on envoie vers la sortie standard, c'est une suite de caractères. Depuis Java 5, une nouvelle méthode permettant d'effectuer une sortie formatée est disponible, la méthode printf. Mais de quoi s'agit-t'il ? Pour le comprendre, voici un extrait de code qui affiche des informations sur la sortie standard :

Et voilà ce que l'exécution du programme affiche à l'écran :

Nom : SPENCER JOHN
Age : 30
Date de naissance : jeu. nov. 20 00:00:00 CET 1975

Ce qu'on désire faire, c'est donc afficher une chaine de caractères, mais y incruster la valeur de différentes variables. On le fait avec l'opérateur de concaténation. L'utilisation des sorties formatées facilite grandement cette tâche et rend le code bien plus lisible. Voici maintenant le même programme avec les sorties formatées introduites en Java 5 :

Le premier argument de la méthode printf est la chaine de caractères à afficher, dans laquelle on incruste des balises. Elles commencent par le caractère % suivi d'un ou plusieurs caractères. Elles indiquent les endroits où seront incrustés la valeur d'une expression.

Ensuite, on donne à la méthode printf toutes les expressions dont on souhaite incruster la valeur dans la chaine de caractères. Il faut donc autant d'expressions qu'il y a de balises dans la chaine de caractères. Dans notre exemple, on a les balises %s, %s, %d et %tc et on a donc quatre expressions qui sont : nom, prenom, age et ddn. La figure 30 reprend les balises les plus courantes.

Balise Description
%s Une chaine de caractères
%d Un entier sous forme décimale
%x Un entier sous forme hexadécimale
%e Un réel sous forme décimale en notation scientifique
%f Un réel sous forme décimale
%t Utilisé pour formater les dates
Balises pour les sorties formatées.

Pour formater une date, on utilise une balise à deux lettres. La première est la lettre t et la seconde permet de formater la date et heure. Par exemple, %tH permet de récupérer l'heure entre 00 et 23. La figure 31 reprend quelques valeurs possibles.

Balise Description
%tH L'heure sur deux caractères entre 00 et 23
%tk L'heure entre 0 et 23
%tM Les minutes entre 00 et 59
%tB Le mois dans la langue courante (exemple Janvier ou January...)
%tY L'année sur quatre chiffres
%tc Le jour et l'heure formatée sous la forme %ta %tb %td %tT %tZ %tY
Balises pour les sorties formatées pour le temps.

Il faut faire attention à l'ordre et aux types des expressions que l'on passe comme paramètres à la méthode printf. En effet, si le nombre ou les type des expressions ne correspondent pas à ceux implicitement définit par la chaine de formatage, une erreur d'exécution apparait. Prenons l'exemple suivant :

On veut donc afficher la valeur d'une variable de type double, mais on a utilisé %d qui est une balise pour des nombres entiers. On se retrouve avec une erreur de type IllegalFormatConversionException lors de l'exécution du programme :

x : Exception in thread "main" java.util.IllegalFormatConversionException: d != java.lang.Double
	at java.util.Formatter$FormatSpecifier.failConversion(Unknown Source)
	at java.util.Formatter$FormatSpecifier.printInteger(Unknown Source)
	at java.util.Formatter$FormatSpecifier.print(Unknown Source)
	at java.util.Formatter.format(Unknown Source)
	at java.io.PrintStream.format(Unknown Source)
	at java.io.PrintStream.printf(Unknown Source)
	at chapter4.FormattedOutput.main(FormattedOutput.java:10)

Une autre erreur peut apparaitre s'il manque des paramètres. Dans l'exemple suivant, on a défini trois balises, mais on n'a fournit qu'un seul paramètre et une erreur de type MissingFormatArgumentException se produit.

x : 2 Exception in thread "main" java.util.MissingFormatArgumentException: Format specifier 'f'
	at java.util.Formatter.format(Unknown Source)
	at java.io.PrintStream.format(Unknown Source)
	at java.io.PrintStream.printf(Unknown Source)
	at chapter4.FormattedOutput2.main(FormattedOutput2.java:10)

Nombre variable de paramètres

La méthode printf est un exemple de méthode dont le nombre de paramètres qu'il faut lui fournir lors de son appel n'est pas fixe. Cette possibilité d'avoir un nombre variable de paramètres (varargs) a été introduite en Java 5. Comme on le verra au chapitre 8, cette fonctionnalité est liée aux tableaux. Dans la documentation de l'API Java, on repère de telles méthodes en voyant un type de paramètre suivi de trois points, comme le paramètre args présenté ci-dessous :

Option des balises

Enfin, sachez également que les balises des sorties formatées peuvent également être paramétrisées grâce à des options. Commençons avec les nombres réels dont on peut préciser le nombre de chiffres désirés après la virgule. Pour cela, on place entre le % et le f un point suivi du nombre de chiffres que l'on veut après la virgule.

Des options existent également pour l'affichage des nombres entiers. On peut préciser le nombre total de chiffres désirés et remplir à gauche ou à droite avec des espaces ou des zéros. Pour cela, on place entre le % et le d le nombre de chiffres désirés au total. Si ce nombre commence par un zéro, le remplissage se fera avec des zéros, sinon il se fera avec des espaces.

Pour en savoir plus, il suffit de consulter la documentation de la classe java.util.Formatter qui permet de gérer ces sorties formatées.

Formatage de String

La méthode printf permet d'effectuer une sortie formatée vers la sortie standard. Parfois, il est intéressant d'utiliser la puissance des sorties formatées pour construire un objet String. La classe String contient une méthode de classe format qui permet de réaliser cela :

Sortie d'erreur standard

La sortie d'erreur standard (stderr) se comporte comme l'entrée standard. C'est également un objet de type PrintStream qui est représentée par l'objet System.err. Par contre, contrairement à la sortie standard qui permet d'afficher des informations à destination de l'utilisateur du programme, la sortie d'erreur standard permet d'afficher des informations concernant l'erreur, celles-ci étant plutôt destinées au programmeur ou à l'administrateur de la machine.

Entrée standard

L'entrée standard est représentée par l'objet System.in. Un petit tour sur la documentation de l'API Java nous permet de voir qu'il s'agit d'un objet de type InputStream. Si on consulte la documentation de cette classe, on se rend compte qu'elle n'offre pas beaucoup de méthodes de haut niveau, les seules méthodes disponibles permettent de lire les données de l'entrée standard par octets. Il faudra attendre jusqu'au chapitre 9 traitant des entrées/sorties pour pouvoir directement lire les données tapées par l'utilisateur à la console.

Classe Scanner

Avec Java 5 est apparue la classe Scanner se trouvant dans le package java.util. Celle-ci facilite la lecture de données depuis l'entrée standard. Voici tout de suite un exemple qui permet de lire une chaine de caractères tapée sur l'entrée standard :

Il faut tout d'abord créer un objet de type Scanner en lui passant comme paramètre System.in étant donné que l'on veut lire des données depuis l'entrée standard. Ensuite, on invoque la méthode nextLine() qui renvoie toute la ligne tapée à la console sous forme d'un String.

On peut également directement lire des données de type primitif grâce aux méthodes nextXxxXxx est un type primitif. Il existe également les méthodes nextBigInteger et nextBigDecimal qui permettent de lire respectivement des objets BigInteger et BigDecimal. La méthode next permet de lire l'élément suivant sous forme d'un String. Enfin, pour savoir de quel type est l'élément suivant, on peut utiliser les méthodes hasNextXxx.

L'exemple utilise ces différentes méthodes. Ce programme va faire la somme de tous les entiers encodés sur l'entrée standard jusqu'à ce que l'utilisateur tape bye. À ce moment, la somme est affichée et le programme s'arrête.

Il ne faut pas oublier de fermer l'objet Scanner avec la méthode close une fois qu'on a terminé. L'exemple précédent montre également que l'on peut quitter un programme avec la méthode de classe exit de la classe System. Cette méthode prend un int en paramètre; nous n'allons pas entrer dans les détails, vous pouvez simplement utiliser 0.