On voit trois parties qui vont donner de l’interactivité à nos programmes :
Entrées/sorties standard
Lecture/écriture dans des fichiers
Sérialisation
On a déjà vu comment afficher le contenu d’une variable avec System.out.println(). On peut aussi utiliser System.out.print() si on veut ne pas avoir de retour à la ligne après l’affichage :
System.out.println()
System.out.print()
System.out.print("Hello "); System.out.print("Bidule");
Va afficher sur la même ligne :
Hello Bidule
Rappel : on peut ajouter des caractères spéciaux (retour à la ligne, tabulations,…) avec un caractère \ devant la lettre ou le symbole :
\
\t Insert a tab. \b Insert a backspace. \n Insert a newline. \r Insert a carriage return. \f Insert a formfeed. \' Insert a single quote character. \" Insert a double quote character. \\ Insert a backslash character in.
Tiré de la documentation oracle.
Pour afficher plusieurs variables au milieu du texte, il faut généralement les concatener avec un +. On peut aussi utiliser la classe MessageFormat qui donne une syntaxe plus agréable, voire même utiliser la méthode printf() déjà vue dans l’initiation en Java :
+
int nbPagesLues = 123; int nbPagesTotal = 1_048; String titre = "Guerre et paix"; String msg = MessageFormat.format( "J'ai déjà lu {0} pages de {2} sur {1} pages, ouf...", nbPagesLues, nbPagesTotal, titre);
La syntaxe est simple, l’indice {0} correspond à nbPagesLues, l’indice *{2} correspond à titre, et ainsi de suite…
Il faut importer MessageFormat au début du fichier :
import java.text.MessageFormat;
Exemple :
import java.util.Date; import java.text.MessageFormat; public class TestFormat { public static void main(String[] args){ int planete = 7; String evenement = "une perturbation dans la Force"; String resultat = MessageFormat.format( "A {1,time} le {1,date}, il y a {2} de la planète numéro {0}.", planete, new Date(), evenement); System.out.println(resultat); } }
Pour cet exemple, il faut aussi importer Date au début du fichier :
import java.util.Date;
Pour lire sur l’entrée standard System.in, on va utiliser la classe Scanner. Une fois le scanner crée, on pourra utiliser les méthodes nextInt() ou next() ou encore nextLine() pour lire les prochaines entrées dans l’entrée standard :
System.in
Scanner
nextInt()
next()
nextLine()
import java.text.MessageFormat; import java.util.Scanner; public class Lire { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("Quelle est votre année de naissance ? "); int annee = sc.nextInt(); System.out.print("Quel est votre nom ? "); String nom = sc.next(); int age = 2023 - annee; System.out.println(MessageFormat.format("Félicitations {0}, vous avez {1} ans !", nom, age)); } }
Voici un exemple d’un programme avec un menu très simple qui propose un choix à l’utilisateur (1 ou 2, et 0 pour quitter). Le menu est affiché à nouveau tant que l’utilisateur n’a pas fait 0 pour quitter. Tien, tant que, c’est un while :)
while
import java.util.Scanner; public class PetitMenu { public static void main(String[] args) { String menu = "\nBienvnue dans mon programme!\n1.Pour afficher ding!\n2.Pour afficher dong!\n0.Pour quitter"; int choix; Scanner sc = new Scanner(System.in); do { System.out.println(menu); choix = sc.nextInt(); if (choix == 1) { System.out.println("ding!"); } else if (choix == 2) { System.out.println("dong!"); } else if (choix == 0) { System.out.println("bye bye..."); } else { System.out.println("Tu fais erreur, cette option n'existe pas !"); } } while (choix != 0); } }
Il existe de nombreuses méthodes pour lire des fichiers en java. On peut lire le fichier caractère par caractère, ou bien ligne par ligne. On va voir deux méthodes ici.
Premièrement, on fait comme dans la lecture de l’entrée standard avec un Scanner :
import java.io.File; import java.io.FileNotFoundException; import java.text.MessageFormat; import java.util.Scanner; public class LireFile { public static void main(String[] args) throws FileNotFoundException { String fileName = "LireFile.java"; File file = new File(fileName); Scanner sc = new Scanner(file); while (sc.hasNextLine()) { System.out.println(sc.nextLine()); } } }
Deuxièmement, on va utiliser une méthode de la classe utilitaire Files (cette classe donne des méthodes static sur les fichiers) qui permet d’obtenir la liste de toutes les lignes :
Files
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; public class LireFile2 { public static void main(String[] args) throws IOException { String fileName = "LireFile2.java"; List<String> lines = Files.readAllLines(Paths.get(fileName)); // on parcourt la liste lines, pour afficher par exemple for (String line : lines) { System.out.println(line); } } }
La deuxième méthode pourra être pratique si on veut garder la liste telle quelle, ou si on aime bien manipuler les listes (qui ont pas mal de méthodes intéressantes).
On va aussi utiliser la classe Files pour écrire. La méthode write permet d’écrire directement une liste dans un fichier. Si le fichier n’existe pas, par défaut il sera crée. Si le fichier existe déjà, alors il sera remplacé :
write
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.Arrays; import java.util.List; public class Ecrit { public static void main(String[] args) throws IOException { String fileName = "test.txt"; List<String> promo = List.of( "sophie","bastien","nicolas","virgile","maureen","tony", "florian","didier","romain","laetitia","francois", "cedric","sebastien","camille","elodie","olivier","robert" ); Files.write(Paths.get(fileName), promo); } }
On peut aussi écrire les éléments un par un, mais si on veut que l’appel à write ajoute à la fin du fichier (au lieu de remplacer le contenu du fichier), il faut ajouter l’option StandardOpenOption.APPEND :
StandardOpenOption.APPEND
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.Arrays; import java.util.List; public class Ecrit { public static void main(String[] args) throws IOException { String fileName = "test.txt"; List<String> promo = List.of( "sophie","bastien","nicolas","virgile","maureen","tony", "florian","didier","romain","laetitia","francois", "cedric","sebastien","camille","elodie","olivier","robert" ); for (String elem : promo) { Files.write(Paths.get(fileName), elem.getBytes(), StandardOpenOption.APPEND); } } }
Remarque : si on veut avoir un retour à la ligne après chaque élément, il faut aussi ajouter un “\n”
Si on appelle plusieurs fois le programme, le fichier va contenir plusieurs fois la liste complète (mode APPEND), on peut donc vouloir supprimer le fichier avant de commencer avec ` deleteIfExists`.
Plus d’infos sur ce bon tutoriel java.
La sérialisation permet d’écrire des instances d’objet dans des fichiers, ou bien de transporter à distance, par exemple via une api rest ou autre.
Il faut distinguer ce mécanisme des exemples précédents dans lesquels on n’écrivait que du texte dans les fichiers. Avec la sérialisation, on écrit directement une représentation d’une instance (avec tous ses attributs).
On retrouvera donc ce mécanisme au moment de voir ce qu’est une api REST, ou vous pouvez aller voir directement ce même cours plus detailé.
Exercices d’application du cours
Corrections des exercices
Cours détaillé
Auteurs : PBouget & JTobelen