Accueil > Programmer avec Java > Les bases de Java >
Entrées et sorties à la console
Survol et attentes
Pour ajouter de lâinteraction Ă un programme, il faut donner la chance Ă lâutilisateur de nous fournir une rĂ©ponse. Dans le contexte dâun programme qui se lance Ă la console, cela veut dire capter les rĂ©ponses tapĂ©es par lâutilisateur au clavier. Dans cette leçon, nous allons voir comment faire ça en Java.
Définitions
- Mot-clé
new - un mot-clĂ© qui crĂ©e une nouvelle instance dâune classe (qui crĂ©e un objet). Ce mot-clĂ© est suivi par une mĂ©thode spĂ©ciale de la classe appelĂ©e le constructeur. Chaque classe dĂ©finit son propre constructeur, alors il faut connaĂźtre les dĂ©tails de la classe pour crĂ©er des objets de cette classe. Votre EDI vous aide avec ces dĂ©tails. La dĂ©claration complĂšte dâun nouvel objet est
Type nom = new Type(arguments, ...);. - Classe
Scanner - une classe qui nous permet de lire une source de texte comme la console, un String ou un fichier de texte. Un objet de type
Scannera accĂšs Ă plusieurs mĂ©thodes dâinstance pour retourner diffĂ©rents types de donnĂ©es. UnScannersaisie toujours du texte, donc les mĂ©thodes commenextInt()etnextDouble()convertissent le texte en nombre et peuvent planter si le format des caractĂšres saisis ne correspond pas au type attendu. Câest pourquoi il y a aussi des mĂ©thodes commehasNextInt()ethasNextDouble()pour valider le format avant de tenter une conversion. - Classe
Locale - une classe qui permet de spĂ©cifier un ensemble de formats rĂ©gionaux, notamment celui des nombres dĂ©cimaux. Par dĂ©faut, le format dĂ©pend du systĂšme dâexploitation donc le programme se comportera diffĂ©remment sur diffĂ©rents ordinateurs. Pour Ă©viter des erreurs de conversion, on peut spĂ©cifier un
Localepour chaqueScanneren utilisant la méthodeuseLocale(). - Objet
System.in - un objet de type
InputStreamqui reprĂ©sente lâentrĂ©e standard du systĂšme dâexploitation, gĂ©nĂ©ralement la console. Lâavantage est quâil est toujours dĂ©fini (ça fonctionne toujours). Le dĂ©savantage est que Windows gĂšre les caractĂšres Unicode diffĂ©remment que le reste du monde, ce qui donne parfois des comportements inattendus et difficiles Ă rĂ©soudre. - Invite de rĂ©ponse
- un message affichĂ© Ă lâutilisateur pour lui indiquer ce quâil doit saisir. Câest une bonne pratique de donner des invites de rĂ©ponse claires et spĂ©cifiques pour Ă©viter des erreurs de saisie. Des bonnes invites de rĂ©ponse rendent toujours lâintĂ©raction plus agrĂ©able pour lâutilisateur.
Liste des méthodes de Scanner les plus courantes :
next(): saisir le prochain mot (jusquâĂ un espace, ignorant les espaces initiaux)nextInt(): saisir le prochain mot et le convertir enintnextDouble(): saisir le prochain mot et le convertir endoublehasNextInt(): vĂ©rifier si le prochain mot est uninthasNextDouble(): vĂ©rifier si le prochain mot est undoublenextLine(): saisir la prochaine ligne de texte (jusquâĂ un retour Ă la ligne)⊠il y a des nuances avec cette mĂ©thode que nous explorerons en dĂ©tail ci-dessous.
Objectifs dâapprentissage
Ă la fin de cette leçon vous devrez ĂȘtre en mesure de :
- Savoir comment déclarer un Scanner pour la console et pour un String
- Savoir utiliser les mĂ©thodes dâinstance dâun Scanner pour obtenir le type de rĂ©ponse dĂ©sirĂ©.
- Expliquer lâimportance dâune invite de rĂ©ponse spĂ©cifique et claire avant lâinstruction de saisie.
- Expliquer câest quoi un
Localeet pourquoi il faut le spécifier si on veut saisir des valeurs décimales.
CritĂšres de succĂšs
- Je peux importer la classe
Scanner, déclarer un Scanner pour la console et utiliser ses méthodesnext,nextIntetnextDoublepour lire des données. - Je peux définir un
LocaleappropriĂ© pour le Scanner si jâai besoin de saisir des valeurs dĂ©cimales. - (enrichissement) Je peux valider les rĂ©ponses fournies par lâutilisateur avec les mĂ©thodes
hasNextIntethasNextDoubleavant de tenter une conversion afin de réduire le nombre de plantages de mes programmes.
Structure gĂ©nĂ©rale dâun programme avec un Scanner
Les Scanner sont utilisĂ©s pour lire du texte Ă partir de diffĂ©rentes sources. Pour commencer, on utilisera un Scanner qui surveille System.in pour complĂ©menter le PrintStream (System.out) quâon utilise dĂ©jĂ pour afficher des messsages texte Ă la console. Bref, les Scanner vont nous permettre de lire des rĂ©ponses de lâutilisateur Ă la console et dâavoir des programmes interactifs.
Si vous ne lâaviez pas devinĂ©,
System.inetSystem.outsont les entrĂ©es et sorties standard de votre systĂšme dâexploitation, notamment la console.
La structure globale dâun programme qui utilise un Scanner est la suivante :
import java.util.*; // importer la définition de Scanner de java.util
void main() {
Scanner console = new Scanner(System.in); // déclarer un Scanner pour la console
// ... le reste du programme
}
Déclarer un Scanner
Le format de la dĂ©claration dâun Scanner est le suivant :
Scanner nom = new Scanner(source);
oĂč nom est le nom de la variable qui contiendra lâobjet Scanner et source est la source de texte que le Scanner lira. Le nom est gĂ©nĂ©ralement un reflĂšt prĂ©cis de la source.
Pour lire de la console
On utilise System.in, lâentrĂ©e standard, comme source.
Scanner console = new Scanner(System.in);
Pour lire un String
On utilise un String comme source.
String text = "Bonjour, le monde!";
Scanner textReader = new Scanner(text);
Fermer un Scanner
On ne ferme jamais le Scanner pour la console parce quâon sâen sert gĂ©nĂ©ralement jusquâĂ la fin du programme interactif. Ce Scanner sera fermĂ© automatiquement en arrivant Ă la fin de la mĂ©thode main.
Par contre, câest important de fermer les Scanner pour toutes les autres sources de texte, comme un fichier ou un String. On ferme un Scanner avec la mĂ©thode close() une fois quâon a finit de le lire. Par exemple :
textReader.close();
Introduction aux mĂ©thodes de Scanner - extraire les donnĂ©es dâun String
Pour comprendre comment les mĂ©thodes de Scanner fonctionnent, on va les tester sur diffĂ©rents String. Les sections plus bas montrent le Scanner dans le contexte dâun programme interactif.
La méthode next() : lire le prochain mot
La mĂ©thode next() saisit le prochain mot - plus spĂ©cifiquement, le prochain âjetonâ - dans le texte. Un jeton est une sĂ©quence de caractĂšres qui nâinclut pas dâespaces. Si la prochaine chose dans le texte commence par un ou plusieurs espaces, ces espaces seront ignorĂ©s en saisissant le jeton. La mĂ©thode next() retourne le jeton saisi.
String words = "\n \tBonjour le monde!";
Scanner wordsReader = new Scanner(words); // Scanner qui utilise le texte 'words' comme source
String word; // variable pour stocker le mot lu
word = wordsReader.next(); // ignore les espaces initiaux puis saisit tout jusqu'au prochain espace, soit "Bonjour"
System.out.println(word);
word = wordsReader.next(); // saisit "le"
System.out.println(word);
word = wordsReader.next(); // saisit "monde!"
System.out.println(word);
wordsReader.close();
Les méthodes nextInt() et nextDouble() : convertir le texte en nombre
Peut ĂȘtre que la ligne de texte suivante reprĂ©sente des informations sur une personne, comme son Ăąge et sa moyenne scolaire. Connaissant le format du texte, on peut utiliser les mĂ©thodes appropriĂ©es pour lire les valeurs.
Les mĂ©thodes nextInt() et nextDouble() saisissent le prochain mot et tentent de le convertir en int ou double respectivement. Si le texte ne peut pas ĂȘtre converti en nombre, le programme plantera, alors il faut faire attention de :
- bien aviser lâutilisateur du format attendu dans un programme interactif
- bien observer les formats du texte dans des fichiers quâon veut lire, comme un fichier qui contiendrait plusieurs lignes de donnĂ©es semblables Ă lâexemple suivant.
String info = "Marie 15 85.5";
Scanner infoReader = new Scanner(info);
String nom = infoReader.next(); // saisir le nom
int age = infoReader.nextInt(); // saisir le texte pour le nombre entier
double moyenne = infoReader.nextDouble(); // saisir le nombre décimal
infoReader.close();
System.out.printf("%s a %d ans et sa moyenne est %.1f\n", nom, age, moyenne);
Si le programme fonctionne correctement, il nous donnera cette sortie :
Marie a 15 ans et sa moyenne est 85.5
Dans notre contexte spĂ©cifique - travailler en français avec des machines configurĂ©es en français - il y a quand mĂȘme un bon risque de plantage parce que le format pour le dĂ©cimal est diffĂ©rent sur un systĂšme anglais (.) que sur un systĂšme français (,). Ă lâinterne, Java utilise toujours le . comme dĂ©cimal, mais il utilisera les formats du systĂšme dans ses Scanner pour interprĂ©ter les rĂ©ponses de lâutilisateur Ă la console.
Donc câest possible que Java prĂ©sume que le format 85,5 est le bon et lance une erreur quand il voit plutĂŽt 85.5. Ce nâest pas un bon systĂšme, mais il y a une façon de dire dans notre programme quel format on veut utiliser.
Spécifier le format des nombres décimaux
Quand on connaĂźt le format des nombres dĂ©cimaux dans le texte Ă lire, ou on dit Ă lâutilisateur quel format utiliser dans sa rĂ©ponse interactive, on devrait spĂ©cifier ce format explicitement dans le code.
On le fait en utilisant la classe Locale (aussi dans java.util) et les valeurs quâelle dĂ©finit par dĂ©faut pour diffĂ©rents formats rĂ©gionaux. Dans notre contexte, on utilise lâune au lâautre des options suivantes :
Locale.CANADA: pour utiliser le.comme séparateur décimalLocale.CANADA_FRENCH: pour utiliser la,comme séparateur décimal
Le code précédent devient alors :
String info = "Marie 15 85.5";
Scanner infoReader = new Scanner(info);
infoReader.useLocale(Locale.CANADA); // spécifie le format "."
String nom = infoReader.next();
int age = infoReader.nextInt();
double moyenne = infoReader.nextDouble();
infoReader.close();
System.out.printf("%s a %d ans et sa moyenne est %.1f\n", nom, age, moyenne);
Maintenant, le programme fonctionne correctement peu importe lâordinateur utilisĂ© pour le lancer.
Version interactive : lire la console
En interagissant Ă la console, câest important de donner des invites de rĂ©ponse claires et spĂ©cifiques Ă lâutilisateur afin quâelle sache quoi taper et avec quel format, si nĂ©cessaire.
Voici un exemple en transformant le programme précédent en un programme interactif :
Scanner console = new Scanner(System.in); // source = entrée standard
console.useLocale(Locale.CANADA_FRENCH); // spécifie le format ","
System.out.print("Quel est votre prénom? "); // invite de réponse
String nom = console.next();
System.out.print("Quel est votre ùge? "); // invite de réponse
int age = console.nextInt();
// invite de réponse qui reflÚte la déclaration du Locale plus haut dans le code
System.out.print("Quelle est votre moyenne? (utilisez le ',' comme décimal) ");
double moyenne = console.nextDouble();
System.out.printf("%s a %d ans et sa moyenne est %.1f\n", nom, age, moyenne);
// notez qu'on n'a pas fermé le Scanner pour la console
Enrichissement : valider la réponse avant de la saisir
Cette section est annotĂ©e comme âavancĂ©eâ parce quâelle incorpore des Ă©lĂ©ments de programmation que nous nâavons pas encore vus avec Java, notamment les opĂ©rations logiques et les boucles. Si vous ne comprenez pas tout de suite, ne vous inquiĂ©tez pas. Vous aurez lâoccasion de revoir ces concepts plus tard dans le cours.
Si vous comprenez bien comment formuler une invite de rĂ©ponse prĂ©cise et comment assurer la cohĂ©rence entre votre invite et ce que vous avez Ă©crit dans votre code, peut-ĂȘtre que vous ne serez pas satisfait de laisser une erreur de frappe par lâutilisateur faire planter votre programme. Câest lĂ quâon peut commencer Ă rendre le code plus tolĂ©rante aux erreurs en les gĂ©rant avant quâelles ne causent des problĂšmes.
Pour valider une rĂ©ponse avant de la saisir, on utilise les mĂ©thodes hasNextInt() et hasNextDouble() pour vĂ©rifier si le prochain mot est convertible en int ou double respectivement. Si la rĂ©ponse est valide, on la saisit, la convertit et la conserve. Sinon, on doit vider le Scanner pour prĂ©parer la saisie suivante, alors on saisit la rĂ©ponse comme texte sans la conserver. On peut Ă©galement afficher un message dâerreur et inviter lâutilisateur Ă rĂ©essayer.

Scanner console = new Scanner(System.in);
System.out.print("Saisissez un nombre entier : ");
while (!console.hasNextInt()) {
console.next(); // vider le Scanner du jeton incorrect
System.out.println("Ce n'est pas un nombre entier valide.");
System.out.print("Saisissez un nombre entier : ");
}
int number = console.nextInt();
System.out.println("Vous avez saisi " + number);
LâopĂ©rateur
!est lâinverse logique (ânotâ). Il transformetrueenfalseetfalseentrue. Dans ce contexte,!console.hasNextInt()signifie âtant que le Scanner nâa pas un nombre entier valide comme prochain jetonâ.
Exercices
đ Tester la comprĂ©hension
aucun quiz de vérification des concepts ici encore
đ ïž Pratique
Travaillez dans le répertoire GitHub partagé par votre enseignant pour la pratique et les exercices.
- Dupliquez tous les exemples dans le fichier
Scanning.java. - Prenez une capture dâĂ©cran de votre Ă©diteur de code et du terminal pour les phases suivantes :
- lâexemple âBonjour le monde!â -> nommez lâimage
4-5-Scanner1.png. - lâexemple âMarie 15 85.5â avec lâajustement pour inclure le bon Local -> nommez lâimage
4-5-Scanner2.png.
- lâexemple âBonjour le monde!â -> nommez lâimage
- lâexemple interactif avec les invites de rĂ©ponse; rĂ©pondez comme vous le voulez -> nommez lâimage
4-5-Scanner3.png. - lâexemple avec la validation de la rĂ©ponse; donnez au moins une mauvaise rĂ©ponse avant de donner une rĂ©ponse valide -> nommez lâimage
4-5-Scanner4.png.