Accueil > Programmer avec Java >
File
: une classe Java qui permet de manipuler des fichiers et des répertoires. On importe cette classe avec import java.io.File;
. File nous permet de créer, supprimer, renommer, etc. des fichiers et des répertoires. Au plus simple, on utilise un objet de type File
comme source pour un Scanner
.
Scanner fileReader = new Scanner(new File("nomDuFichier.txt"))
.FileWriter
: une classe Java qui permet d’écrire des données dans un fichier texte avec la méthode write()
. On importe cette classe avec import java.io.*;
. On a plusieurs options pour le créer un objet de ce type mais les deux les plus communs sont :
new FileWriter("nomDuFichier.txt")
-> En créant ce FileWriter, le contenu existant du fichier sera remplacé par les appels de write
.new FileWriter("nomDuFichier.txt", true)
-> En créant ce FileWriter et en assignant true
au 2e paramètre, on ajoute du contenu à la fin du fichier avec les nouveaux appels de write
.objet anonyme : un objet qui n’a pas de nom, donc qui est utilisable seulement à l’endroit où il est déclaré. On peut créer un objet anonyme directement dans un appel de méthode.
new Scanner(new File("nomDuFichier.txt"))
crée un objet Scanner qui lit le nouvel objet anonyme File
.File inputFile = new File("./data/input.txt");
suivie de Scanner fileReader = new Scanner(inputFile);
.chemin de fichier : séquence de dossiers à partir d’un point de référence, se terminant avec le nom complet du fichier, soit son nom et son extension.
./
../data/input.txt
pour un fichier texte input.txt
qui se trouve dans un dossier data
à la racine du projet.références de dossier spéciales : On peut inclure certaines références spéciales au début d’un chemin comme :
..
pour le dossier parent,.
pour le dossier actuel,~
pour le dossier utilisateur et/
pour le dossier racine.classe de données : une classe qui ne contient que des variables pour stocker des données. On l’utilise pour organiser des données lues d’un fichier texte, notamment en créent un tableau d’objets de cette classe.
À la fin de cette leçon vous devrez être en mesure de :
Parce qu’on essaie d’accéder à une ressource - un fichier - qui n’existe peut-être pas (si on l’a mal nommé ou si le chemin est mal formé ou si son dossier n’a pas été crée en premier), on utilise généralement un bloc try-catch avec ressources pour l’action de lire ou écrire dans un fichier. Le format général est :
1
2
3
4
5
6
7
8
try (déclarer et initialiser la ressource) {
// code pour lire ou écrire dans le fichier
/* retourner une valeur utile et/ou assigner les valeurs lues
à des variables déclarées à l'extérieur du bloc try-catch */
} catch (Exception e) {
// message d'erreur
// retourner/assigner une valeur par défaut
}
Un avantage majeur du bloc try-catch est que la ressource est automatiquement fermée à la fin du bloc, même si une exception est lancée. Cela évite les fuites de ressources et les erreurs de programmation.
Un autre avantage est qu’en cas de plantage, on a une valeur connue qu’on peut utiliser dans une condition pour éviter que le reste du programme ne plante. Par exemple, si on sait que la valeur d’un String
lue revient null
en cas d’erreur, on peut tester si la valeur est null
comme pré-condition pour continuer le programme.
Il y a deux exemples de code dans la leçon sur les exceptions qui représentent des bons points de départ pour lire et écrire des fichiers :
D’autres exemples d’algorithmes incluant des exceptions sont fournis plus bas.
Pour bien lire un fichier, il faut avoir une idée de sa structure ou, mieux, connaître exactement sa structure.
Cela vous permet de développer un plan pour lire le fichier, notamment :
useDelimiter()
next*
pour lire les donnéesuseLocale()
Connaissant la structure des données sur chaque ligne d’un fichier, vous pouvez vous casser la tête à savoir comment organiser toute l’information lue afin de pouvoir l’utiliser dans votre programme et pas seulement l’afficher à l’écran.
La solution est de créer une petite classe qui ne contient aucune méthode mais juste des variables pour stocker les données. On appelle cette classe une classe de données.1 2
Par exemple, plus loin on voit un exemple où on veut lire le mois (String), la température moyenne (double) et la précipitation (int) pour chaque mois de l’année. On pourrait créer une classe WeatherData
avec les variables month
, averageTemp
et precipitation
pour stocker ces données.
1
2
3
4
5
6
7
8
9
10
11
12
/** Définit notre propre structure de données */
class WeatherData {
String month;
double averageTemp;
int precipitation;
}
void main() {
// déclare un tableau qui contient des éléments de type WeatherData
WeatherData[] monthlyWeather = new WeatherData[12];
//... lire les données dans le tableau
}
Sans notre propre type de données on aurait dû utiliser des tableaux séparés de String
, double
et int
pour stocker les données. Cela aurait été plus difficile à lire et à maintenir. Et dans Java, on ne peut retourner qu’une seule valeur d’une méthode, alors on n’aurait pas pu retourner les trois tableaux ensemble. On serait obligé de déclarer ces tableaux globalement (dans la classe).
Dans la boucle de lecture, on peut assigner les valeurs lues aux 3 variables d’instance de chacune des 12 objets de la classe WeatherData
et ensuite retourner le tableau pour l’utiliser dans le reste du programme. Par exemple :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.io.*;
import java.util.*;
void main() {
Scanner fileReader = new Scanner(new File("weather_data2022.txt"));
WeatherData[] monthlyWeather = getWeatherData(fileReader);
filereader.close();
// ...code pour utiliser monthlyWeather
}
class WeatherData {
String month;
double averageTemp;
int precipitation;
}
WeatherData[] getWeatherData(Scanner fileReader) {
WeatherData[] weather = new WeatherData[12]; // créer un tableau de 12 objets
for (int i = 0; i < 12; i++) {
weather[i] = new WeatherData(); // initialiser chaque objet
// initialiser ses variables
weather[i].month = fileReader.next();
weather[i].averageTemp = fileReader.nextDouble();
weather[i].precipitation = fileReader.nextInt();
}
return weather; // retourner le tableau
}
Une classe comme WeatherData
est le début de la programmation orientée-objet, le thème du cours ICS4U.
Il y a plusieurs façons de lire un fichier texte avec un Scanner.
next*
pour lire les données.Il y a plusieurs autres approches possibles, alors ces trois-ci ne sont que des points de départ. Dans tous les cas, l’algorithme ressemble généralement à ceci :
…
Travaillez dans le répertoire GitHub partagé par votre enseignant pour la pratique et les exercices.
FileReading1.java
et y ajouter sa méthode main.moodJournal.txt
qui contient la ligne suivante : 2024-04-27 heureux
. Implémentez un algorithme dans main
qui :
moodJournal.txt
dans un bloc try-catch et affiche son contenu à la console.moodJournal.txt
dans un bloc try-catch et assigne les valeurs individuelles à des variables pour la date et l’humeur (deux String
). Préparer un message à l’extérieur du bloc try-catch qui affiche la date et l’humeur.moodJournal.txt
dans un bloc try-catch et assigne les valeurs individuelles à des variables pour l’année, le mois, le jour (3 int
) et l’humeur (String
).
Trois pistes pour Scanner les parties de la date : (1) modifiez le délimiteur du Scanner (“-“ et “ “), (2) utilisez d’abord
next
pour la date entière et déclare un Scanner sur ce texte avec un délimiteur de “-“ pour saisir les int, (3) utilisersplit("-")
sur la date entière etInteger.parseInt
sur chaque élément du tableau.
FileReading2.java
et y ajouter sa méthode main.FileWriting.java
et y ajouter sa méthode main.Java offre aussi une structure de données appelée Record
qui est plus spécifique qu’une classe mais exactement pour ce genre de situation, mais qui masque les données, ce qui est un concept plus avancé qu’on voit seulement en 12e année. ↩
Les exemples de code ci-dessous appliquent le JEP 463 (classe abstraite, méthode main
d’instance), alors seulement la classe interne pour la structure de données est déclarée dans le code. ↩