- Apprendre
- Informatique et numérique
- Programmation
- Java orienté objet : classes, collections, héritage et tests
- Exceptions et fichiers en Java
Exceptions et fichiers en Java
try, catch et finally. Lève tes propres exceptions et conçois des classes d’exceptions qui indiquent précisément ce qui s’est passé. Lis et écris ensuite des fichiers texte en maîtrisant les chemins, les encodages et les fins de ligne, ferme correctement chaque fichier avec l’instruction try avec gestion des ressources et construis un programme qui gère les fichiers manquants et les données incorrectes.DébutantUnité 9 sur 11 de la formation Formation : Java orienté objet : classes, collections, héritage et tests
Ce que tu vas apprendre
- Reconnais une exception lorsqu’un programme échoue, lis la trace de pile pour trouver où et pourquoi elle s’est produite, et situe toute exception dans la hiérarchie des classes Java comme contrôlée ou non contrôlée.
- Lis une exception et sa trace de pileExplique ce qui se produit lorsqu’une instruction lève une exception, nomme les exceptions d’exécution courantes et leurs causes, et utilise une trace de pile pour localiser le problème.
- Distingue les exceptions contrôlées des exceptions non contrôléesSitue toute exception dans la hiérarchie sous Throwable, détermine si elle est contrôlée ou non contrôlée et applique la règle selon laquelle les exceptions contrôlées doivent être interceptées ou déclarées.
- Lis une exception et sa trace de pile
- Intercepte les exceptions qu’un programme peut prévoir, reprends l’exécution de façon adaptée, gère plusieurs types dans le bon ordre et exécute le code de nettoyage quelle que soit l’issue.
- Intercepte une exception et reprends l’exécutionÉcris une instruction try-catch, suis son déroulement et reprends l’exécution après une saisie incorrecte au lieu de laisser le programme s’arrêter brutalement.
- Gère plusieurs types d’exceptions dans le bon ordreUtilise plusieurs clauses catch ou une capture multiple, classe-les de la plus spécifique à la plus générale et décide où un bloc try doit commencer et se terminer.
- Exécute le code de nettoyage avec finallyAjoute un bloc finally, suis le moment où il s’exécute dans chaque chemin d’une instruction try et évite les erreurs qui amènent finally à masquer des problèmes.
- Intercepte une exception et reprends l’exécution
- Signale les problèmes depuis tes propres méthodes avec throw, déclare les exceptions contrôlées avec throws et crée des classes d’exceptions qui indiquent précisément aux appelants ce qui s’est passé.
- Lève des exceptions et déclare-les avec throwsValide les arguments et l’état des objets en levant des exceptions standard, déclare les exceptions contrôlées dans les en-têtes de méthodes et décide où une exception doit être gérée.
- Crée des classes d’exceptions personnalisées et conserve la causeÉcris tes propres classes d’exceptions contrôlées ou non contrôlées, lève-les avant de modifier l’état d’un objet et encapsule une exception de bas niveau sans la perdre.
- Lève des exceptions et déclare-les avec throws
- Indique au programme le bon fichier, comprends comment le texte est stocké sous forme d’octets et de lignes, et assure-toi que chaque fichier ouvert est fermé avec l’instruction try avec gestion des ressources.
- Manipule les chemins, les encodages et les fins de ligneConstruis des chemins vers des fichiers, prévois où Java cherche un chemin relatif et explique l’effet des encodages de caractères, des fins de ligne et des formats numériques sur les fichiers texte.
- Ferme automatiquement les ressources avec l’instruction try avec gestion des ressourcesUtilise l’instruction try avec gestion des ressources pour ouvrir et fermer des fichiers et d’autres ressources, prévois leur ordre de fermeture et explique comment cette instruction évite de perdre des exceptions.
- Manipule les chemins, les encodages et les fins de ligne
- Lis des fichiers texte ligne par ligne et transforme leurs lignes en données, écris et ajoute des résultats dans des fichiers, puis combine le tout dans un programme qui gère les fichiers manquants et les enregistrements incorrects.
- Lis un fichier texte et transforme ses lignes en donnéesLis un fichier avec Scanner, Files.readAllLines ou BufferedReader, découpe et convertis chaque ligne, puis ignore ou signale les lignes qui ne correspondent pas au format attendu.
- Écris dans des fichiers texte et ajoute du texte à leur finÉcris du texte dans un fichier nouveau ou existant, ajoute du texte sans effacer son contenu et assure-toi que tout ce qui est écrit parvient effectivement au fichier.
- Construis un programme robuste de traitement de fichiersCombine lecture, analyse, exceptions et écriture dans un programme qui s’arrête proprement en cas d’erreur au niveau du fichier entier, ignore et signale les enregistrements incorrects et évite une sortie partielle.
- Lis un fichier texte et transforme ses lignes en données
Exceptions et fichiers en Java : cours
1Comprends ce que sont les exceptions et comment Java les classe
Un programme peut compiler correctement et tout de même échouer lorsqu’il reçoit un tableau vide ou un texte invalide, ou lorsqu’un fichier est manquant. L’objet exception et sa trace de pile te renseignent sur cet échec. Remonte les appels de méthodes actifs dans la trace, puis utilise la hiérarchie des classes pour déterminer si Java exige une décision de gestion à la compilation. Tu pourras ainsi distinguer les bogues à corriger des problèmes prévisibles après lesquels ton programme peut reprendre son exécution.
1.1 Trouve l’instruction qui échoue
Une exception est un objet qui décrit un problème interrompant un programme en cours d’exécution. La lever arrête l’instruction en cours. Java ignore le travail normal restant jusqu’à trouver un gestionnaire correspondant ; à défaut, l’exception remonte par les méthodes appelantes.
Reconnaître le type de problème
Un point-virgule manquant est une erreur de compilation : le programme ne peut pas compiler. Une exception se produit lorsque du code compilé s’exécute avec des données qui déclenchent un problème.
| Exception | Déclencheur typique |
|---|---|
ArithmeticException | Division entière par zéro |
ArrayIndexOutOfBoundsException | a[3] lorsque le tableau est de longueur 3 |
IndexOutOfBoundsException | list.get(list.size()) |
NullPointerException | Appel d’une méthode par une référence null |
NumberFormatException | Integer.parseInt("12a") |
InputMismatchException | Scanner.nextInt() rencontre "ten" |
ClassCastException | Transtypage d’un objet vers une classe dont il n’est pas une instance |
Les indices de tableau commencent à 0 : une longueur de 3 signifie donc que les indices valides sont 0, 1 et 2. La division en virgule flottante suit d’autres règles : 10.0 / 0 produit Infinity ; elle ne lève pas l’exception de division entière.
Lire une trace depuis le haut
Voici une classe complète, sans ligne vide avant la première ligne :
public class Average {
static int average(int[] values) {
int sum = 0;
for (int value : values) sum += value;
return sum / values.length;
}
public static void main(String[] args) {
int[] values = new int[0];
System.out.println(average(values));
}
}
Le tableau est vide, sa longueur est donc de 0. La division à la ligne 5 échoue. Voici la trace :
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Average.average(Average.java:5)
at Average.main(Average.java:9)
- Lis la première ligne pour connaître la classe et le message de l’exception.
- Lis le premier cadre
atpour trouver où le problème a été détecté. - Descends pour trouver les appelants :
maina appeléaverageà la ligne 9. - Si les premiers cadres appartiennent à la bibliothèque Java, trouve le premier cadre qui nomme ta propre classe. Pour un appel à
Integer.parseIntqui échoue, des cadres de bibliothèque peuvent précéder l’appel dans ton code.
La trace suit la pile d’appels, c’est-à-dire la chaîne des appels de méthodes actifs. Elle t’indique où chercher, mais la valeur incorrecte peut avoir été créée plus tôt. Ici, la division détecte le problème ; l’appelant a fourni le tableau vide. Décide si une entrée vide doit être rejetée ou traitée avant le calcul d’une moyenne.
Examiner l’objet exception
e.getMessage() renvoie le message et peut renvoyer null. e.toString() comprend le nom de la classe et, s’il existe, le message. e.printStackTrace() affiche la trace sur le flux d’erreur standard. Une section Caused by: montre une exception antérieure conservée dans une exception qui l’encapsule.
Les messages NullPointerException produits par la JVM indiquent normalement l’expression nulle. Une exception créée explicitement peut en revanche avoir un message personnalisé ou aucun message. Remonte la référence jusqu’à l’endroit où elle aurait dû recevoir un objet.
Une exception non gérée qui sort de main met fin au thread principal ; cela met fin à un programme à un seul thread. Corrige dans le code les bogues comme les indices incorrects. Prévois une reprise pour les problèmes externes attendus, comme un fichier manquant ou une saisie utilisateur invalide.
Points clés
- Une exception interrompt l’exécution normale ; les instructions ignorées ne reprennent pas automatiquement.
- Lis la classe et le message de l’exception, puis suis les cadres de pile depuis l’échec détecté jusqu’à ses appelants.
- Des cadres de bibliothèque peuvent apparaître avant le premier cadre de ton propre code.
- L’instruction qui échoue peut révéler une valeur incorrecte créée plus tôt.
- Corrige les bogues de programmation et gère les erreurs prévisibles de saisie ou de fichier.
1.2 Exceptions contrôlées et non contrôlées
Les classes d’exceptions utilisent les règles d’héritage que tu connais déjà. Un objet levé d’une sous-classe appartient aussi à sa superclasse, ce qui explique à la fois les catégories d’exceptions de Java et la façon dont un gestionnaire leur correspond.
Suivre la hiérarchie
Seuls les objets de Throwable ou de ses sous-classes peuvent être levés. Deux branches principales se trouvent en dessous :
Throwable
Error
OutOfMemoryError
StackOverflowError
Exception
RuntimeException
IllegalArgumentException
NumberFormatException
NullPointerException
IndexOutOfBoundsException
ArrayIndexOutOfBoundsException
IOException
FileNotFoundException
NoSuchFileException
Error décrit des défaillances graves de l’environnement d’exécution. Une application ordinaire ne devrait pas tenter de reprendre l’exécution après un épuisement du tas ou de la pile dû à une récursion sans fin. Exception décrit des problèmes qu’une application peut gérer, y compris sa branche RuntimeException.
| Catégorie | Classes | Exigence du compilateur |
|---|---|---|
| Non contrôlées | RuntimeException, Error et leurs sous-classes | La capture ou la déclaration est facultative |
| Contrôlées | Toutes les autres sous-classes de Throwable | Les intercepter ou les déclarer lorsque le code peut les lever |
Les deux types sont levés à l’exécution. Le mot « contrôlée » indique que le compilateur vérifie la gestion de l’exception ; il ne désigne pas un moment antérieur où l’échec se produirait. Non contrôlée ne signifie pas non plus sans danger : une référence nulle non gérée peut arrêter un programme.
Appliquer la capture ou la déclaration
La lecture d’un fichier peut échouer même dans un code correct. Une méthode auxiliaire peut laisser la décision à son appelant :
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
class Names {
static List<String> load(Path file) throws IOException {
return Files.readAllLines(file);
}
}
Files.readAllLines peut lever l’exception contrôlée IOException. La déclaration transmet cette possibilité à l’appelant, qui doit lui aussi l’intercepter ou la déclarer. Supprimer throws IOException sans ajouter de gestionnaire empêche la compilation de la méthode auxiliaire. Une méthode utilisant Integer.parseInt n’a pas d’obligation comparable imposée par le compilateur, car NumberFormatException est non contrôlée.
Les erreurs contrôlées décrivent souvent des situations qu’un appelant peut prévoir, comme la disparition d’un fichier. Les erreurs d’exécution indiquent souvent des bogues ou des arguments invalides. Ces raisons sont utiles pour la conception, mais c’est la chaîne de superclasses qui détermine la catégorie. Une classe personnalisée qui étend RuntimeException reste non contrôlée même lorsqu’un appelant pourrait reprendre l’exécution.
Faire correspondre les gestionnaires grâce à l’héritage
catch (IOException e) peut gérer une FileNotFoundException ou une NoSuchFileException. catch (Exception e) intercepte aussi les exceptions d’exécution ; il peut transformer un bogue du code en message trompeur sur une saisie. catch (Throwable e) atteint aussi la branche Error et convient rarement à une reprise ordinaire.
Pour classer une classe inconnue, remonte sa chaîne d’héritage dans la documentation de l’API. InputMismatchException étend NoSuchElementException, qui étend RuntimeException : elle est donc non contrôlée. InterruptedException étend Exception hors de la branche des exceptions d’exécution : elle est donc contrôlée. Déclarer un type non contrôlé dans une clause throws est autorisé, mais ne change pas sa catégorie.
Points clés
RuntimeException,Erroret toutes leurs sous-classes sont non contrôlées.- Les autres sous-classes de
Throwablesont contrôlées ; le code qui peut les lever doit les intercepter ou les déclarer. - Les exceptions contrôlées comme les exceptions non contrôlées se produisent à l’exécution.
- Une clause catch pour une superclasse correspond aussi à ses sous-classes.
- Un gestionnaire général pour
Exceptionpeut masquer des bogues de programmation. - Classe une exception inconnue à partir de sa chaîne de superclasses.
2Gère les exceptions avec try, catch et finally
La gestion d’un échec change les instructions exécutées ensuite. Un gestionnaire utile doit correspondre à l’exception et laisser le programme prêt à continuer, tandis que le nettoyage doit aussi s’exécuter sur les chemins qui se terminent prématurément. Suis les conversions et les boucles étape par étape, place les gestionnaires spécifiques avant les gestionnaires généraux et entoure d’un bloc protégé les opérations qui doivent échouer ensemble. Suis ensuite le comportement de finally lorsqu’une exception se propage ou qu’une méthode effectue un retour.
2.1 Reprends l’exécution après l’échec d’une conversion
Un bloc try délimite un travail qui peut échouer. Un bloc catch correspondant donne au programme une action utile à effectuer ensuite, comme demander une autre valeur. La gestion de l’exception ne relance pas à elle seule l’instruction qui a échoué.
Suivre les branches
System.out.println("A");
try {
System.out.println("B");
int value = Integer.parseInt("4x");
System.out.println("C");
} catch (NumberFormatException e) {
System.out.println("D: " + e.getMessage());
}
System.out.println("E");
La sortie est A, B, D: For input string: "4x" et E, chacun sur sa propre ligne. La conversion échoue ; Java ignore donc C et entre dans le gestionnaire correspondant. Lorsque ce gestionnaire se termine normalement, l’exécution reprend après l’ensemble de l’instruction. Si la conversion réussit, le gestionnaire est ignoré. Si le bloc lève une ArithmeticException, ce gestionnaire ne correspond pas ; l’exception se propage.
Réessayer avec une nouvelle saisie
Lis une ligne entière avant de la convertir. La boucle ci-dessous accepte un entier et gère la fin de la saisie au clavier en signalant qu’aucune valeur n’a été fournie :
import java.util.Scanner;
class WholeNumbers {
static int readWholeNumber(Scanner in) {
while (in.hasNextLine()) {
String line = in.nextLine();
try {
return Integer.parseInt(line.trim());
} catch (NumberFormatException e) {
System.out.println("Please enter a whole number.");
}
}
throw new IllegalStateException("No number supplied");
}
}
Pour les saisies "twenty" et "20", le gestionnaire affiche le message une fois, la boucle lit une nouvelle ligne et la méthode renvoie 20. trim() supprime les caractères blancs en début et en fin de chaîne : sans cela, Integer.parseInt(" 20") échoue. La conversion accepte un signe facultatif et des chiffres représentant un entier dans l’intervalle autorisé.
Un scanner qui lit des jetons nécessite une autre correction. Lorsque nextInt() rencontre "ten", son InputMismatchException laisse ce jeton non lu. Intercepter l’exception et rappeler nextInt() répète l’échec indéfiniment. Consomme le jeton incorrect avec next() ou écarte la ligne avec nextLine() avant de réessayer. hasNextInt() peut vérifier un jeton avant la conversion.
Garder un état utilisable après la reprise
Une variable déclarée dans try n’existe que dans ce bloc. Si le code ultérieur a besoin du résultat, déclare-la à l’extérieur et assure-toi que chaque chemin qui continue lui affecte une valeur valide :
int quantity;
try {
quantity = Integer.parseInt("bad");
} catch (NumberFormatException e) {
quantity = 0;
}
System.out.println(quantity);
Zéro ne convient ici que si le programme le définit comme une valeur de remplacement valide. Laisser quantity sans affectation dans le gestionnaire provoque une erreur de compilation liée à l’affectation certaine.
Intercepte le type précis que tu peux gérer. Un gestionnaire vide fait silencieusement perdre le problème ; un catch (Exception e) général peut présenter un bogue de référence nulle comme un nombre incorrect. La reprise doit redemander une saisie, ignorer un élément, choisir une valeur par défaut valide, signaler l’échec ou transmettre une exception explicite. Pour des bornes simples et prévisibles, vérifie d’abord : index >= 0 && index < list.size() évite les indices de liste négatifs comme les indices trop grands.
Points clés
- Un gestionnaire correspondant s’exécute après que le reste du bloc
tryayant échoué a été ignoré. - Une boucle doit lire une nouvelle saisie avant de réessayer.
Scanner.nextInt()laisse non lu un jeton de type incorrect.- Chaque chemin qui continue doit laisser les variables utilisées ensuite initialisées avec des valeurs adaptées.
2.2 Choisis les gestionnaires et les opérations qu’ils protègent
Un fichier peut être manquant, illisible ou rempli d’enregistrements mal formés. Ces échecs nécessitent des réponses différentes. Plusieurs gestionnaires permettent à un try de les distinguer, tandis que la position du bloc détermine quelle partie du travail s’arrête en cas d’échec.
Placer d’abord les gestionnaires spécifiques
Java teste les gestionnaires de haut en bas et exécute le premier qui correspond. Il ne continue pas à exécuter les gestionnaires suivants pour la même exception.
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
class FirstCount {
static void show(Path file) {
try {
int count = Integer.parseInt(Files.readString(file).trim());
System.out.println(count);
} catch (NoSuchFileException e) {
System.out.println("File not found: " + file.toAbsolutePath());
} catch (IOException e) {
System.out.println("Could not read: " + file.toAbsolutePath());
} catch (NumberFormatException e) {
System.out.println("The file must contain one whole number.");
}
}
}
NoSuchFileException étend IOException, elle doit donc venir en premier. Inverser leur ordre rend le gestionnaire spécifique inaccessible et empêche la compilation. L’exception de conversion n’a pas de lien avec IOException ; ces deux gestionnaires peuvent donc apparaître dans n’importe quel ordre.
Un gestionnaire d’exception contrôlée doit aussi correspondre à une exception que le travail protégé peut lever. Intercepter IOException autour de la seule instruction int count = 5; est rejeté, car ce bloc ne peut pas la lever. Cette restriction ne s’applique pas de la même façon aux types non contrôlés ni aux types généraux Exception et Throwable.
Partager un gestionnaire lorsque la réponse est la même
Une capture multiple réunit des types d’exceptions sans lien entre eux avec | :
try {
String[] parts = "Ana".split(",");
int age = Integer.parseInt(parts[1]);
System.out.println(age);
} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
System.out.println("Invalid record: " + e.getMessage());
}
Ici, l’absence du deuxième champ déclenche l’exception d’indice. Un champ présent mais non numérique déclencherait l’exception de conversion, et les deux reçoivent la même réponse. Le paramètre de la capture multiple est implicitement final. Les types proposés ne peuvent pas être une sous-classe et sa superclasse : FileNotFoundException | IOException est invalide car IOException couvre déjà les deux.
Décider ce qu’un échec doit faire ignorer
Considère les textes "3", "x" et "5". Avec un try autour de toute la boucle, le traitement s’arrête à "x" et la somme obtenue jusque-là est de 3. Place le try dans la boucle pour reprendre séparément après chaque élément :
int sum = 0;
for (String text : new String[] {"3", "x", "5"}) {
try {
sum += Integer.parseInt(text);
} catch (NumberFormatException e) {
System.out.println("Skipped: " + text);
}
}
System.out.println(sum);
Ce code affiche Skipped: x puis 8. La boucle continue car son corps a géré l’échec de cet enregistrement. Avec des gestionnaires imbriqués, la recherche part du bloc protégé le plus interne et progresse vers l’extérieur ; si un gestionnaire interne ne correspond pas, un gestionnaire extérieur peut encore intercepter l’exception. Choisis la plus petite unité de travail qui doit échouer dans son ensemble : un enregistrement pour des données incorrectes, l’opération sur le fichier pour une erreur de lecture.
Points clés
- Java exécute au plus un gestionnaire correspondant pour chaque exception.
- Intercepte une sous-classe avant sa superclasse.
- La capture multiple partage une réponse entre des types d’exceptions sans lien entre eux.
- La capture multiple ne peut pas combiner une superclasse avec sa sous-classe.
- Place la reprise après une erreur d’enregistrement dans la boucle pour continuer avec les enregistrements suivants.
2.3 Exécute le nettoyage avant de quitter le bloc
Certaines opérations doivent avoir lieu, qu’une action réussisse ou échoue. Un bloc finally s’exécute lorsque le contrôle quitte son instruction try, y compris lorsqu’une exception se propage ou qu’une méthode effectue un retour.
Suivre une exception sans gestionnaire correspondant
try {
System.out.println("1");
int[] values = new int[2];
values[2] = 7;
System.out.println("2");
} catch (NumberFormatException e) {
System.out.println("3");
} finally {
System.out.println("4");
}
System.out.println("5");
Seuls 1 et 4 s’affichent avant la propagation de l’ArrayIndexOutOfBoundsException. L’indice 2 est hors du tableau de deux éléments. Le gestionnaire ne correspond pas, mais finally s’exécute quand même. L’instruction qui affiche 5 se trouve hors du bloc de nettoyage : l’exception qui se propage la fait donc ignorer.
Si le travail protégé lève à la place une NumberFormatException correspondante après avoir affiché 1, le gestionnaire affiche 3, le nettoyage affiche 4 et l’exécution continue jusqu’à 5. Sur un chemin où tout réussit, aucun gestionnaire ne s’exécute, mais le nettoyage a quand même lieu.
Les valeurs de retour sont préparées avant le nettoyage
class Cleanup {
static int result() {
try {
return 1;
} finally {
System.out.println("cleanup");
}
}
}
L’expression de retour est d’abord évaluée. Java affiche ensuite cleanup et l’appelant reçoit 1. Un break ou un continue qui quitte une région protégée exécute aussi son nettoyage avant que le transfert de contrôle prenne effet.
Ne place pas return dans finally. Un return 2; à cet endroit remplacerait la valeur de retour en attente et pourrait même écarter une exception en attente. Une exception levée par le nettoyage peut de la même façon remplacer l’échec d’origine. Le nettoyage ne doit pas introduire un second résultat concurrent. L’option -Xlint:finally du compilateur émet un avertissement lorsqu’un bloc finally ne peut pas se terminer normalement.
Fermer un objet uniquement s’il a été ouvert
L’ancien schéma manuel nécessite une variable visible par le bloc de nettoyage :
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Scanner;
class ManualRead {
static void firstLine(Path file) throws IOException {
Scanner sc = null;
try {
sc = new Scanner(file, StandardCharsets.UTF_8);
if (sc.hasNextLine()) System.out.println(sc.nextLine());
if (sc.ioException() != null) throw sc.ioException();
} finally {
if (sc != null) sc.close();
}
}
}
Si l’ouverture échoue, sc vaut toujours null ; la condition empêche donc le nettoyage de lever une nouvelle exception de référence nulle. Pour les objets qui peuvent être fermés, l’instruction try avec gestion des ressources supprime ces tâches de suivi et gère plus sûrement les erreurs concurrentes.
finally ne garantit pas le nettoyage si la machine s’arrête. System.exit met fin à la JVM sans exécuter ce nettoyage ; un arrêt brutal ou une coupure de courant l’empêche aussi. Une boucle infinie qui ne quitte jamais le bloc n’atteint pas non plus son finally.
Points clés
finallys’exécute après une fin normale, des exceptions interceptées ou non interceptées et des transferts de contrôle commereturn.- Une expression de retour est évaluée avant l’exécution du nettoyage.
- Le code après une instruction
tryest ignoré lorsqu’une exception se propage ;finallyest tout de même atteint. - Un retour ou une exception levée dans
finallypeut masquer le résultat d’origine. - L’instruction try avec gestion des ressources est le choix habituel pour fermer les ressources associées aux fichiers.
- L’arrêt de la JVM ou un bloc qui ne se termine jamais peut empêcher le nettoyage.
3Lève des exceptions et conçois les tiennes
Une demande invalide est plus facile à diagnostiquer avant qu’elle ne modifie un objet. Tes méthodes peuvent rejeter des arguments ou un état invalides avec des exceptions standard et signaler des problèmes propres au domaine avec des classes personnalisées. La déclaration d’une méthode informe les appelants des erreurs contrôlées ; l’héritage limite ce qu’une redéfinition peut ajouter. Lorsque tu transformes une erreur de bas niveau en une exception plus utile, conserve sa cause pour que l’appelant dispose à la fois du contexte et des éléments de diagnostic d’origine.
3.1 Signale les arguments et les états invalides
Tes méthodes peuvent rejeter des demandes invalides avant de modifier un objet. Choisis une exception qui indique le problème et permet à l’appelant d’y répondre.
Lever un objet immédiatement
class Percentage {
private int value;
public void setPercentage(int value) {
if (value < 0 || value > 100) {
throw new IllegalArgumentException(
"percentage must be 0 to 100, was " + value);
}
this.value = value;
}
}
L’appel setPercentage(120) lève une exception avec le message percentage must be 0 to 100, was 120. L’affectation n’a pas été exécutée, donc le champ conserve sa valeur précédente. C’est l’échec immédiat : signale la demande invalide à l’endroit où tu peux l’expliquer. La même vérification dans un constructeur empêche le renvoi d’un objet invalide.
throw exige un objet exception, comme dans throw new IllegalArgumentException("bad quantity");. Un nom de classe seul n’est pas un objet. Une instruction ordinaire placée directement après un throw inconditionnel dans le même bloc est inaccessible.
| Problème | Exception standard |
|---|---|
| Un argument a une valeur invalide | IllegalArgumentException |
| L’état de l’objet ne permet pas l’appel | IllegalStateException |
Une référence d’objet obligatoire vaut null | NullPointerException |
| La classe ne propose pas l’opération | UnsupportedOperationException |
| L’indice est hors d’une collection | IndexOutOfBoundsException |
Objects.requireNonNull(name, "name must not be null"), de java.util.Objects, permet de vérifier facilement qu’une référence n’est pas nulle. Le refus d’ajouter un article à une commande déjà envoyée est un problème d’état ; une quantité d’articles négative est un problème d’argument.
Déclarer ce qui peut sortir de la méthode
Une méthode auxiliaire de lecture de fichier peut déclarer l’erreur contrôlée qu’elle peut transmettre :
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
class NameLoader {
static List<String> loadNames(Path file) throws IOException {
return Files.readAllLines(file);
}
}
throw est une instruction exécutable. throws fait partie de la déclaration de méthode et indique aux appelants les erreurs contrôlées qu’ils doivent traiter. Il n’intercepte pas une erreur et ne permet pas à la méthode de continuer après celle-ci. Chaque appelant doit intercepter IOException ou la déclarer à son tour. Une clause catch peut aussi relancer le même objet avec throw e;.
Intercepte l’exception là où une réponse utile est possible. Une méthode auxiliaire ne peut généralement pas demander à l’utilisateur de choisir un autre fichier, mais main le peut. Afficher « erreur » et renvoyer une liste vide ferait confondre un fichier manquant avec un fichier réellement vide. Dans une petite expérience, main peut déclarer throws IOException ; un programme terminé gère les erreurs prévisibles avec des messages utiles. Les types non contrôlés peuvent être déclarés pour les documenter, même si le compilateur ne l’exige pas.
Respecter le contrat hérité
Si une interface déclare read() throws IOException, une méthode qui la redéfinit peut déclarer IOException, une sous-classe contrôlée plus spécifique ou aucune exception contrôlée. Elle ne peut pas élargir la déclaration à Exception. Elle peut déclarer des types non contrôlés. Une redéfinition de Object.toString() ne peut pas ajouter IOException, puisque la méthode héritée ne déclare aucune exception contrôlée. Les appels effectués par le type interface doivent toujours traiter l’IOException déclarée, même lorsqu’une implémentation n’en déclare aucune.
Points clés
- Utilise
throwavec un objet exception pour arrêter une opération invalide. - Valide les données avant de modifier les champs ou les collections.
throwsdéclare une erreur possible ; il ne la gère pas.- Intercepte l’exception là où une reprise utile est possible ; sinon, transmets l’erreur à l’appelant.
- Les méthodes redéfinies ne peuvent pas ajouter d’exceptions contrôlées nouvelles ou plus générales.
3.2 Décris les erreurs propres au domaine et préserve leurs causes
Une exception standard suffit souvent. Crée une classe personnalisée lorsque les appelants doivent reconnaître un problème propre au programme, comme un stock insuffisant ou un enregistrement de données mal formé, et y répondre différemment.
Choisir la superclasse avec soin
Étendre Exception crée une exception contrôlée. Étendre RuntimeException crée une exception non contrôlée. Choisis une exception contrôlée lorsque les appelants doivent prévoir une erreur du domaine après laquelle ils peuvent reprendre l’exécution ; choisis une exception non contrôlée pour une mauvaise utilisation ou un bogue de programmation.
class OutOfStockException extends Exception {
public OutOfStockException(String message) {
super(message);
}
}
super(message) stocke le message dans le mécanisme d’exception hérité, donc getMessage() le renvoie. Par convention, le nom de la classe se termine par Exception. Des champs et des accesseurs supplémentaires peuvent exposer des détails structurés, comme les quantités demandée et disponible.
Laisser le stock inchangé après un échec
import java.util.HashMap;
class Inventory {
private final HashMap<String, Integer> stock = new HashMap<>();
Inventory() {
stock.put("pens", 12);
}
void remove(String item, int quantity) throws OutOfStockException {
if (quantity <= 0) {
throw new IllegalArgumentException("quantity must be positive");
}
int available = stock.getOrDefault(item, 0);
if (quantity > available) {
throw new OutOfStockException("Requested " + quantity
+ " of " + item + ", only " + available + " in stock");
}
stock.put(item, available - quantity);
}
}
Avec 12 stylos au départ, en retirer 5 en laisse 7. Une demande ultérieure de 10 lève une exception et il en reste 7, car la mise à jour intervient après toutes les vérifications. L’appelant doit gérer ou déclarer l’erreur contrôlée de stock ; l’erreur de quantité invalide est non contrôlée. Un programme qui doit répondre différemment à un article inconnu pourrait utiliser une UnknownItemException apparentée, les deux types propres au domaine ayant InventoryException comme classe de base.
Encapsuler sans perdre le problème d’origine
Une méthode d’analyse peut transformer une erreur de conversion de bas niveau en une erreur au niveau d’un enregistrement :
class InvalidRecordException extends Exception {
public InvalidRecordException(String message) {
super(message);
}
public InvalidRecordException(String message, Throwable cause) {
super(message, cause);
}
}
Dans la méthode d’analyse, un gestionnaire peut faire ceci :
catch (NumberFormatException e) {
throw new InvalidRecordException(
"Line 3: quantity is not a number: x", e);
}
L’exception qui encapsule l’autre donne à l’appelant une catégorie explicite et un numéro de ligne. Sa méthode getCause() renvoie la NumberFormatException d’origine et la trace affichée conserve une section Caused by:. Construire une nouvelle exception avec uniquement l’ancien message fait perdre l’objet d’origine et sa trace.
java.io.UncheckedIOException est une classe d’encapsulation non contrôlée fournie spécifiquement pour IOException. Ses constructeurs acceptent la cause, avec un message facultatif. Elle peut transmettre une erreur de fichier depuis une méthode redéfinie qui ne peut pas ajouter de déclaration d’exception contrôlée. L’encapsulation change le type que voit l’appelant ; elle ne répare pas le problème de fichier. Pour les décisions ordinaires dans une boucle, utilise des conditions et break, sans inventer d’exceptions pour le déroulement courant.
Points clés
- Les classes personnalisées permettent aux appelants de reconnaître des erreurs précises propres au domaine.
- Étends
Exceptionpour une classe contrôlée ouRuntimeExceptionpour une classe non contrôlée. - Appelle
super(message)pour conserver un diagnostic utile. - Valide toute la demande avant de modifier l’état.
- Transmets l’exception d’origine comme cause lorsque tu l’encapsules.
UncheckedIOExceptiontransmet uneIOExceptionsous forme d’erreur non contrôlée.
4Localise les fichiers et ferme les ressources correctement
Un fichier texte doit être trouvé, décodé et fermé correctement. Un chemin relatif dépend du répertoire de travail, tandis que les octets ne deviennent des caractères lisibles qu’avec le bon encodage. Les nombres sous forme de texte et les fins de ligne impliquent aussi des choix pour assurer la portabilité. Une fois un fichier ouvert, l’instruction try avec gestion des ressources le libère à chaque sortie et garde l’erreur principale visible si la fermeture échoue aussi. Ces choix rendent le code de lecture et d’écriture ultérieur plus fiable.
4.1 Rends les fichiers texte utilisables sur différents ordinateurs
Un fichier stocke des octets, tandis que ton programme manipule des caractères et des nombres. Pour réussir une lecture, il faut le bon emplacement, le bon encodage de caractères et une convention claire pour les lignes et les nombres sous forme de texte.
Trouver l’emplacement réel
Un chemin relatif part du répertoire de travail du programme. Il ne part pas du dossier qui contient le code source. Un chemin absolu part de la racine du système de fichiers, comme /home/ana/data/scores.txt, ou de la racine d’un lecteur sous Windows.
Path file = Path.of("data", "scores.txt");
System.out.println(System.getProperty("user.dir"));
System.out.println(file.toAbsolutePath());
System.out.println(file.getFileName());
Importe java.nio.file.Path. Créer ce Path n’ouvre rien et ne vérifie aucune existence. toAbsolutePath() révèle où Java cherchera et getFileName() donne scores.txt. Un environnement de développement intégré utilise souvent le dossier du projet comme répertoire de travail. Les barres obliques dans "data/scores.txt" fonctionnent sur Windows, Linux et macOS. Dans un littéral de chemin Windows, les barres obliques inverses doivent être échappées, comme dans "C:\\data\\scores.txt". L’ancienne classe java.io.File représente aussi un emplacement ; convertis avec toPath() ou toFile().
Associer les octets aux caractères
UTF-8 encode tous les caractères Unicode. Les caractères latins de base occupent un octet ; les autres en occupent de deux à quatre. Le texte « café » contient quatre caractères mais cinq octets en UTF-8 car « é » en occupe deux. Lire ces octets comme de l’ISO-8859-1 peut produire « café ». Utilise l’encodage employé pour l’écriture.
Les méthodes de Files pour le texte utilisent UTF-8 par défaut. Des classes comme FileWriter et un scanner ouvert sans jeu de caractères utilisent le jeu de caractères par défaut, qui est devenu UTF-8 avec Java 18 ; les installations plus anciennes peuvent utiliser un autre encodage. StandardCharsets.UTF_8, de java.nio.charset, rend le choix explicite. Des octets invalides lus par Files.readAllLines produisent MalformedInputException, une sous-classe de IOException.
Lire les lignes sans conserver leurs fins
| Convention | Séquence d’échappement dans une chaîne Java |
|---|---|
| Fin de ligne Linux et macOS | \n |
| Fin de ligne Windows typique | \r\n |
Avec un terminateur après chaque ligne, « a » et « b » nécessitent quatre octets avec des fins de ligne LF et six avec des fins de ligne CRLF. BufferedReader.readLine(), Files.readAllLines et Scanner.nextLine() retirent les fins de ligne reconnues. Découper une chaîne complète avec split("\n") laisse le \r de Windows ; la conversion de "12\r" avec parseInt échoue donc. Privilégie les méthodes de lecture de lignes ou supprime les caractères blancs autour du texte. System.lineSeparator() et le spécificateur de format %n produisent la fin de ligne du système courant.
Garder un format numérique cohérent dans les fichiers
Integer.parseInt accepte un entier sous forme de texte, sans séparateur décimal. Double.parseDouble("3.5") accepte un point ; Double.parseDouble("3,5") échoue. Ces méthodes d’analyse ignorent les paramètres régionaux. Les méthodes numériques de Scanner et le formatage décimal ordinaire suivent les paramètres régionaux : des paramètres allemands ou néerlandais peuvent donc attendre "3,5" et produire "3,50". Utilise scanner.useLocale(Locale.ROOT) et String.format(Locale.ROOT, "%.2f", value) pour des données dont le séparateur décimal est un point ; importe java.util.Locale.
Les emplacements introuvables produisent souvent NoSuchFileException avec Files ou Scanner(Path), tandis que les anciens constructeurs prenant un nom de fichier peuvent produire FileNotFoundException. Les erreurs d’autorisation peuvent produire AccessDeniedException. Ce sont des erreurs d’entrée-sortie contrôlées : une expression de chemin correcte ne suffit pas à les empêcher.
Points clés
- Les chemins relatifs sont résolus à partir du répertoire de travail.
- Créer un
Pathn’ouvre pas le fichier et ne vérifie pas son existence. - Utilise le même encodage en lecture et en écriture ; choisis explicitement UTF-8 lorsque les valeurs par défaut peuvent varier.
- Les méthodes de lecture de lignes retirent les terminateurs LF, CRLF et CR.
Double.parseDoubleutilise un point ; les méthodes numériques sensibles aux paramètres régionaux nécessitent un choix de paramètres.- L’ouverture et la lecture de fichiers nécessitent toujours la gestion des exceptions contrôlées.
4.2 Laisse Java fermer chaque ressource ouverte
Un fichier ouvert utilise une ressource du système d’exploitation. Sa fermeture la libère et vide le tampon d’un objet d’écriture. Un oubli de fermeture peut épuiser la limite de fichiers ouverts, faire perdre du texte en attente dans un tampon ou empêcher un autre programme de modifier le fichier.
Déclarer les ressources dans l’en-tête de try
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
class Lines {
static void show(Path file) throws IOException {
try (BufferedReader in =
Files.newBufferedReader(file, StandardCharsets.UTF_8)) {
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
}
}
}
L’en-tête ouvre le lecteur. Le corps l’utilise et Java le ferme lorsque le corps se termine normalement, effectue un retour ou lève une exception. Aucun finally séparé n’est nécessaire. Il n’y a pas de gestionnaire ici, donc toute erreur contrôlée est toujours transmise à l’appelant par throws IOException.
Une ressource doit implémenter AutoCloseable. Cette interface déclare close() et autorise Exception ; sa sous-interface Closeable restreint l’erreur contrôlée déclarée à IOException. Les lecteurs, les objets d’écriture et Scanner remplissent cette condition. Une String ne la remplit pas. Les variables de l’en-tête sont implicitement finales et disponibles dans le corps, mais pas dans les blocs catch ou finally de cette instruction. Java 9 et les versions ultérieures autorisent aussi une variable existante finale ou effectivement finale : try (in) { ... }.
Fermer dans l’ordre inverse
Sépare les ressources par des points-virgules :
try (BufferedReader in = Files.newBufferedReader(source);
java.io.BufferedWriter out = Files.newBufferedWriter(target)) {
String line;
while ((line = in.readLine()) != null) {
out.write(line);
out.newLine();
}
}
Il s’agit d’un bloc dans une méthode qui déclare IOException, avec des chemins source et target distincts. Java ouvre d’abord in, puis out, et ferme out avant in. Si l’ouverture de out échoue, le lecteur déjà ouvert est tout de même fermé. Ouvrir un objet d’écriture sur le chemin d’entrée tronquerait cette entrée ; les chemins doivent donc différer pour cette copie directe.
La fermeture des ressources a lieu avant les clauses catch et finally appartenant à la même instruction. Ces gestionnaires peuvent recevoir les erreurs provenant de l’ouverture, de l’utilisation ou de la fermeture des ressources.
Garder l’erreur principale visible
Supposons que le corps lève une exception d’enregistrement, puis que la fermeture du lecteur lève une IOException. L’instruction try avec gestion des ressources propage l’exception du corps et lui rattache l’erreur de fermeture comme exception supprimée. getSuppressed() permet de la récupérer et la trace affiche une section Suppressed:. L’erreur d’origine du corps reste visible. Si le corps réussit et que seule la fermeture échoue, l’exception de fermeture se propage normalement.
Si plusieurs erreurs se produisent pendant la fermeture, Java tente quand même les fermetures restantes. Un simple finally { resource.close(); } peut au contraire remplacer une erreur du corps en attente par une erreur de nettoyage.
Utilise ce schéma pour les ressources de fichiers dont ton code est responsable. Fermer un scanner sur System.in ferme aussi l’entrée clavier du programme, empêchant les lectures ultérieures. Garde plutôt la responsabilité de l’entrée standard partagée au niveau du programme au lieu de la fermer dans une méthode auxiliaire.
Points clés
- L’instruction try avec gestion des ressources ferme les ressources ouvertes avec succès lors des sorties normales et exceptionnelles.
- Seuls les objets
AutoCloseablepeuvent être utilisés comme ressources. - Les ressources s’ouvrent de gauche à droite et se ferment de droite à gauche.
- La fermeture précède les blocs catch et finally de la même instruction.
- Une erreur du corps reste l’erreur principale ; les erreurs de fermeture ultérieures sont supprimées.
- La fermeture automatique ne remplace pas la règle de capture ou de déclaration.
- Fermer un scanner ferme aussi sa source d’entrée si celle-ci peut être fermée.
5Lis et écris des fichiers texte
Le traitement de fichiers relie des octets externes aux objets et aux résultats utilisés par ton programme. Lis les lignes avec une méthode adaptée à la taille de l’entrée, valide les champs avant la conversion et écris en choisissant explicitement de remplacer le contenu ou d’y ajouter du texte. Un rapport complet doit répondre différemment à un enregistrement incorrect et à un fichier inutilisable. Construis le résultat avant de l’enregistrer, puis utilise un fichier temporaire et un déplacement atomique pris en charge lorsqu’une destination existante doit être protégée.
5.1 Lis des lignes et transforme-les en objets
La lecture te donne du texte. L’analyse donne un sens à ce texte : un effectif, un âge ou un objet. Sépare ces deux opérations afin qu’un enregistrement incorrect ne ressemble pas à une erreur de lecture du fichier.
Choisir la quantité à conserver en mémoire
| Méthode | Résultat et utilisation |
|---|---|
Files.readAllLines(path) | Une liste contenant toutes les lignes ; pratique pour les petits fichiers |
Files.readString(path) | Une chaîne qui conserve les fins de ligne |
BufferedReader.readLine() | Une ligne à la fois ; null signale la fin |
Scanner.hasNextLine() / nextLine() | Lecture pratique ligne par ligne |
Importe java.nio.file.Files et Path, ainsi que les types de lecteurs ou de collections que tu utilises. Les méthodes de Files pour le texte utilisent UTF-8 par défaut. Un BufferedReader doit être placé dans une instruction try avec gestion des ressources et signale les erreurs de lecture avec IOException. Lire une ligne à la fois évite de conserver toute l’entrée en mémoire, sauf si ton traitement stocke ensuite tous les enregistrements.
Un scanner doit aussi être fermé et nécessite une vérification d’erreur supplémentaire :
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Scanner;
class ScanFile {
static void show(Path file) throws IOException {
try (Scanner sc = new Scanner(file, StandardCharsets.UTF_8)) {
while (sc.hasNextLine()) {
System.out.println(sc.nextLine());
}
if (sc.ioException() != null) throw sc.ioException();
}
}
}
L’ouverture peut lever directement une exception. Pendant la lecture, Scanner traite une erreur d’entrée-sortie sous-jacente comme une fin d’entrée et l’enregistre ; ioException() permet de la récupérer. Sans cette vérification finale, une lecture partielle peut sembler réussie.
Compter les lignes physiques, puis analyser
Pour les lignes d’entrée "12", "15", "abc", une ligne vide et "9", incrémente le numéro de ligne avant de décider d’ignorer une ligne blanche. Convertis chaque ligne non blanche avec Integer.parseInt(line.trim()) dans son propre try. Signale "Line 3: not a number: abc" et continue. La somme des valeurs valides est de 36 et leur effectif est de 3, ce qui donne une moyenne de 12,0. Calcule (double) sum / count pour conserver une éventuelle partie fractionnaire et vérifie d’abord que l’effectif n’est pas nul.
Vérifier les champs avant d’utiliser leurs indices
Des données simples séparées par des virgules peuvent devenir des objets. Ici, la première ligne est un en-tête obligatoire ; chaque enregistrement suivant contient un nom non vide et un âge entier :
String[] parts = line.split(",", -1);
if (parts.length != 2 || parts[0].isBlank() || parts[1].isBlank()) {
System.out.println("Line " + lineNumber + ": expected name and age");
continue;
}
try {
int age = Integer.parseInt(parts[1].trim());
people.add(new Person(parts[0].trim(), age));
} catch (NumberFormatException e) {
System.out.println("Line " + lineNumber + ": invalid age");
}
Ce fragment de corps de boucle suppose l’existence de line, lineNumber, d’une List<Person> nommée people et d’un constructeur Person(String, int). Ignore l’en-tête "name,age" avant cette étape d’analyse ; sinon, la conversion numérique de "age" échoue. Les enregistrements "Ana,34", "Ben,29" et "Chen,41" totalisent 104 ans et donnent une moyenne d’environ 34,67.
Un simple split(",") supprime les champs vides en fin de ligne : "Eve," ne produit qu’un seul élément. La limite -1 conserve le deuxième champ vide afin que la validation puisse le signaler. Vérifie toujours la longueur avant parts[1]. Le seul découpage ne traite pas les virgules entre guillemets, comme celle du nom dans ""Smith, Ana",34" ; le CSV complet nécessite un analyseur CSV.
Points clés
- Choisis des méthodes qui lisent tout le fichier pour les entrées de taille raisonnable ou une boucle de lecture pour les grandes entrées.
- Vérifie
Scanner.ioException()après la lecture pour détecter une erreur de lecture masquée. - Compte les lignes d’origine du fichier même lorsque des lignes blanches ou des enregistrements sont ignorés.
- Vérifie le nombre de champs et les valeurs obligatoires avant d’utiliser les indices et d’effectuer les conversions.
- Ignore un en-tête avant d’analyser les enregistrements.
- Un simple découpage ne peut pas analyser les champs CSV entre guillemets.
5.2 Écris le texte complet et choisis quand ajouter en fin de fichier
Ouvrir un fichier de sortie peut le modifier immédiatement. Choisis entre remplacer son contenu et ajouter du texte à la fin avant d’ouvrir l’objet d’écriture, puis termine en le fermant pour que le texte en attente dans le tampon ne reste pas en mémoire.
Remplacer ou ajouter à la fin
Files.writeString(path, text) écrit une chaîne. Files.write(path, lines) écrit un ensemble de lignes parcourable, en ajoutant le séparateur de ligne du système après chacune, y compris la dernière. Avec leurs options par défaut, les deux créent un fichier manquant et tronquent un fichier existant.
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
class RunLog {
static void recordStart(Path log) throws IOException {
Files.writeString(log, "started" + System.lineSeparator(),
StandardCharsets.UTF_8,
StandardOpenOption.CREATE, StandardOpenOption.APPEND);
}
}
CREATE permet de créer un fichier ; APPEND conserve l’ancien contenu et ajoute du texte à la fin. APPEND seul échoue si le fichier est absent. L’ajout n’insère pas de séparateur manquant avant ton texte : si un fichier existant se termine au milieu d’une ligne, les caractères suivants prolongent cette ligne.
L’ancienne classe FileWriter possède un indicateur d’ajout : new FileWriter("log.txt", StandardCharsets.UTF_8, true). Sans ajout en fin de fichier, un nouveau FileWriter ou un PrintWriter ouvert par nom de fichier tronque aussi un fichier existant. N’ouvre jamais un objet d’écriture qui remplace le contenu sur une entrée que tu dois encore lire.
Choisir un objet d’écriture et repérer les erreurs
BufferedWriter prend en charge write et newLine(), et signale les erreurs d’écriture sous forme d’exceptions contrôlées :
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Locale;
class ReportWriter {
static void write(Path file) throws IOException {
try (BufferedWriter out =
Files.newBufferedWriter(file, StandardCharsets.UTF_8)) {
out.write("Readings: 3");
out.newLine();
out.write(String.format(Locale.ROOT, "Average: %.2f", 3.0));
out.newLine();
}
}
}
Le fichier contient deux lignes : "Readings: 3" et "Average: 3.00". Locale.ROOT impose le point décimal. newLine(), println et %n utilisent tous la fin de ligne du système ; un \n littéral écrit LF sur tous les systèmes.
Un PrintWriter propose les méthodes pratiques print, println et printf, mais celles-ci enregistrent les erreurs d’entrée-sortie au lieu de les lever. checkError() vide le tampon et indique l’état de son indicateur d’erreur. Pour vérifier aussi les erreurs de fermeture finale, conserve l’accès à l’objet d’écriture et vérifie après sa fermeture. Pour un code qui doit propager les erreurs d’écriture de manière fiable, utilise BufferedWriter ou les méthodes Files.
Compléter le cycle
Les objets d’écriture mettent la sortie en tampon. flush() transmet le texte en attente ; close() vide le tampon et libère le fichier. L’instruction try avec gestion des ressources garantit qu’une fermeture est tentée à chaque sortie, mais ne peut pas garantir la réussite d’une écriture sur disque.
Pour enregistrer une personne, écris son nom, une virgule et son âge entier, puis une fin de ligne. Formate les nombres décimaux avec Locale.ROOT pour qu’un appel ultérieur à Double.parseDouble puisse les lire. L’ouverture d’un fichier ne crée pas un répertoire parent manquant : utilise Files.createDirectories(folder) lorsque sa création est voulue, ou signale l’échec. Une écriture peut échouer après une troncation ou une sortie partielle ; utilise un fichier temporaire et un déplacement atomique lorsque la destination doit être protégée.
Points clés
- L’écriture par défaut crée un fichier manquant et tronque un fichier existant.
- Utilise
CREATEavecAPPENDpour conserver l’ancien contenu et permettre la création d’un journal. - La fermeture vide le tampon de sortie et libère la ressource.
PrintWriterenregistre les erreurs d’écriture ;checkError()permet de les détecter.BufferedWriteret les méthodesFilespropagent les erreurs d’entrée-sortie.- Utilise UTF-8 et
Locale.ROOTpour écrire et relire du texte de manière portable. - Écrire un fichier ne crée pas les dossiers parents manquants.
5.3 Construis un rapport sans masquer les erreurs
Un programme robuste de traitement de fichiers doit gérer les erreurs à deux niveaux. Un enregistrement incorrect peut être ignoré et signalé ; une erreur de lecture ou d’enregistrement du fichier arrête la tâche. Calcule un résultat complet avant de toucher à sa destination.
Lire, valider, calculer, enregistrer
Le programme complet ci-dessous lit un en-tête facultatif "date,temperature" suivi d’enregistrements simples à deux champs. Les dates sont des indications non vides ; les températures sont des nombres finis en degrés Celsius. Il ignore et signale les enregistrements mal formés, y compris les lignes vides. L’exception contrôlée imbriquée sépare les problèmes d’enregistrement des problèmes de fichier.
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.AtomicMoveNotSupportedException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.Locale;
public class TemperatureReport {
static class InvalidRecordException extends Exception {
InvalidRecordException(String message) { super(message); }
InvalidRecordException(String message, Throwable cause) {
super(message, cause);
}
}
static List<String> readLines(Path file) throws IOException {
return Files.readAllLines(file, StandardCharsets.UTF_8);
}
static double parseTemperature(String line, int lineNumber)
throws InvalidRecordException {
String[] parts = line.split(",", -1);
if (parts.length != 2 || parts[0].isBlank()
|| parts[1].isBlank()) {
throw new InvalidRecordException("Line " + lineNumber
+ ": expected a date label and a temperature");
}
try {
double value = Double.parseDouble(parts[1].trim());
if (!Double.isFinite(value)) {
throw new InvalidRecordException("Line " + lineNumber
+ ": temperature must be finite");
}
return value;
} catch (NumberFormatException e) {
throw new InvalidRecordException("Line " + lineNumber
+ ": not a number: " + parts[1], e);
}
}
static String summarize(List<String> lines) {
int count = 0;
int skipped = 0;
double sum = 0;
double min = Double.POSITIVE_INFINITY;
double max = Double.NEGATIVE_INFINITY;
for (int i = 0; i < lines.size(); i++) {
String line = lines.get(i);
if (i == 0 && line.equals("date,temperature")) continue;
try {
double value = parseTemperature(line, i + 1);
sum += value;
count++;
min = Math.min(min, value);
max = Math.max(max, value);
} catch (InvalidRecordException e) {
skipped++;
System.err.println(e.getMessage());
}
}
if (count == 0) {
return String.format(Locale.ROOT,
"No valid readings%nSkipped lines: %d%n", skipped);
}
return String.format(Locale.ROOT,
"Valid readings: %d%nAverage (°C): %.2f%n"
+ "Minimum (°C): %.2f%nMaximum (°C): %.2f%n"
+ "Skipped lines: %d%n",
count, sum / count, min, max, skipped);
}
static void writeSummary(Path file, String text) throws IOException {
Path target = file.toAbsolutePath();
Path temp = Files.createTempFile(target.getParent(), "report-", ".tmp");
try {
Files.writeString(temp, text, StandardCharsets.UTF_8);
Files.move(temp, target, StandardCopyOption.ATOMIC_MOVE);
} catch (IOException e) {
try {
Files.deleteIfExists(temp);
} catch (IOException cleanup) {
e.addSuppressed(cleanup);
}
throw e;
}
}
public static void main(String[] args) {
Path input = Path.of("readings.csv");
Path output = Path.of("summary.txt");
try {
List<String> lines = readLines(input);
String report = summarize(lines);
writeSummary(output, report);
System.out.println("Saved: " + output.toAbsolutePath());
} catch (NoSuchFileException e) {
System.err.println("File or folder not found: " + e.getFile());
} catch (AtomicMoveNotSupportedException e) {
System.err.println("Could not save atomically: "
+ output.toAbsolutePath());
} catch (IOException e) {
System.err.println("Could not process " + input.toAbsolutePath()
+ " or save " + output.toAbsolutePath() + ": " + e.getMessage());
}
}
}
Suivre une exécution
Utilise ces cinq lignes d’entrée sans en-tête :
2026-03-01,4.5
2026-03-02,6.0
2026-03-03,abc
2026-03-04,-1.5
missing comma
Les lignes 1, 2 et 4 produisent trois mesures valides. La somme est de 9,0 ; la moyenne est de 3,00 °C, le minimum de -1,50 °C et le maximum de 6,00 °C. Les lignes 3 et 5 produisent des diagnostics et le rapport indique deux lignes ignorées. Le gestionnaire d’analyse se trouve dans la boucle, donc chaque enregistrement incorrect laisse les enregistrements suivants accessibles. Mettre à jour les sommes uniquement après une analyse réussie empêche l’intégration des valeurs rejetées.
Double.parseDouble accepte des chaînes particulières comme "NaN" et "Infinity". Double.isFinite les rejette ici car elles ne peuvent pas servir de températures mesurées ordinaires. Un fichier vide, un fichier ne contenant que l’en-tête ou des enregistrements tous invalides conduisent à la branche où l’effectif est nul, avant la division ou l’utilisation du minimum et du maximum initiaux.
Protéger la destination
La lecture et le calcul se terminent avant le début de l’enregistrement. Files.writeString ouvre et ferme son propre fichier, mais peut échouer après en avoir écrit une partie. Le programme écrit donc dans un fichier temporaire du dossier de destination, le ferme et demande ATOMIC_MOVE. Lorsque cette opération est prise en charge, le déplacement rend le résultat terminé visible en une seule opération du système de fichiers.
Le remplacement atomique d’une cible existante dépend de l’implémentation. Le programme signale tout déplacement ou remplacement non pris en charge et ne réessaie jamais avec un déplacement non atomique. Une erreur de nettoyage est rattachée à l’exception d’origine au lieu de la remplacer. La visibilité atomique ne garantit pas la conservation des données en cas de coupure de courant.
Vérifier Files.exists(input) au préalable ne peut pas garantir la lecture ultérieure : un fichier peut disparaître ou devenir inaccessible après la vérification. Gère l’opération elle-même. Avant de te fier à un programme de traitement, essaie une entrée manquante, des dossiers de sortie manquants, des fichiers vides ou ne contenant que l’en-tête, des fins de ligne CRLF, du texte accentué et des enregistrements mal formés. Les messages destinés à l’utilisateur doivent nommer le chemin concerné ; pour déboguer une exception qui en encapsule une autre, il faut aussi sa cause d’origine et sa trace de pile.
Points clés
- Gère les erreurs d’enregistrement dans la boucle et les erreurs au niveau du fichier entier à l’extérieur.
- Valide un enregistrement complet avant de mettre à jour les compteurs ou les sommes.
- Vérifie qu’il existe des enregistrements valides avant de calculer une moyenne.
- Termine la lecture et les calculs avant d’ouvrir le fichier de sortie.
- Écris et ferme un fichier temporaire, puis demande un déplacement atomique pour protéger la destination.
- Signale qu’un remplacement atomique n’est pas pris en charge au lieu de recourir silencieusement à une autre méthode.
- Garde les causes d’origine et les erreurs de nettoyage disponibles pour le diagnostic.
Exceptions et fichiers en Java : exemples
1Remonte d’une erreur à sa cause
11 étapes
- 1IntroductionUn programme peut compiler et tout de même échouer
Une valeur d’entrée peut faire échouer du code Java valide pendant son exécution. L’objet exception t’indique le type de problème qui s’est produit et la trace de pile montre quels appels de méthodes étaient actifs.
Suis d’abord une conversion entière qui échoue. Utilise ensuite les mêmes règles d’héritage qui permettent d’utiliser les objets d’une sous-classe comme objets de leur superclasse pour déterminer ce que le compilateur t’oblige à gérer.
- 2ExempleObserve l’arrêt de la conversion
Une méthode
loadCountexécute ces instructions :System.out.print("start "); int count = Integer.parseInt("eight"); System.out.print("finish");Elle affiche
start, puis lèveNumberFormatException. L’affectation ne se termine pas etfinishest ignoré. Un gestionnaire correspondant peut prendre le relais, mais l’instruction qui a échoué ne reprend pas après la gestion de l’erreur. - 3ExplicationSuis les appels actifs
Supposons que
mainait appeléloadCount, qui a appeléInteger.parseInt. Ces appels font partie de la pile d’appels. L’exception remonte lorsqu’une méthode n’a pas de gestionnaire correspondant.parseIntéchoue d’abord,loadCountne peut pas terminer son travail normal et l’appelant a la possibilité de gérer l’erreur. Si elle sort demainsans être gérée, Java signale l’exception et le thread principal se termine. - 4ExempleTrouve ton premier cadre de pile
Une trace peut contenir ces cadres de l’application après ceux de la bibliothèque Java :
at Counts.loadCount(Counts.java:14) at Counts.main(Counts.java:5)Examine d’abord la ligne 14 : c’est l’appel de ton code le plus proche du point de détection. La ligne 5 t’indique où
loadCounta été appelé. La première ligne de l’exception donne sa classe et son message ; ne confonds pas le cadre inférieur de l’appelant avec l’instruction qui a utilisé en premier le texte incorrect. - 5DéfiTrouve la sortie ignorée
Une méthode auxiliaire affiche
A, appelleInteger.parseInt("q2"), puis afficheraitB. Son appelant intercepteNumberFormatExceptionet afficheC. Quelles lettres s’affichent et pourquoi ?---reveal---
ApuisC. La conversion lève une exception avantB; la propagation transmet l’erreur au gestionnaire correspondant de l’appelant. Les instructions restantes de la méthode auxiliaire sont abandonnées, donc la reprise ne revient pas afficherB. - 6ConseilCherche au-delà de l’instruction détectée
L’instruction où une erreur est détectée utilise peut-être une valeur incorrecte créée plus tôt. Une erreur de référence nulle t’invite à rechercher où cette référence aurait dû recevoir un objet.
Utilise
getMessage()pour le texte du diagnostic etprintStackTrace()pour la chaîne d’appels. Un message peut êtrenull; une sectionCaused by:fournit une autre exception conservée dans une exception qui l’encapsule. - 7ExplicationUtilise la chaîne de superclasses
Throwableest la classe de base des objets qui peuvent être levés. Ses branches principales sontErroretException;RuntimeExceptionse trouve sousException.RuntimeException,Erroret toutes leurs sous-classes sont non contrôlées. Les autres sous-classes deThrowablesont contrôlées. Les deux catégories correspondent à des erreurs pendant l’exécution ; « contrôlée » désigne la vérification de leur gestion par le compilateur, et non un autre moment où l’exception serait levée. - 8ExempleCompare un analyseur et un lecteur de fichier
NumberFormatExceptionétendIllegalArgumentException, qui étendRuntimeException; un appel àInteger.parseIntn’a donc pas de gestionnaire obligatoire.IOExceptionétendExceptionhors de cette branche. Un appel àFiles.readStringdoit intercepter l’éventuelleIOExceptionou la déclarer avecthrows. Une erreur de fichier peut avoir des causes externes même lorsque le code appelant est correct. - 9DéfiClasse une erreur inconnue
BadRecordExceptionétend directementException. Une méthode auxiliaire déclare qu’elle peut lever ce type. Que doit faire son appelant et quand cette obligation est-elle vérifiée ?---reveal---
L’intercepter ou déclarer un type contrôlé applicable dans la déclaration de la méthode appelante. Le compilateur impose cette obligation car la classe se trouve hors des branches non contrôlées. Le fait qu’une exécution particulière réussisse ne supprime pas l’exigence au niveau de la déclaration.
- 10DéfiExplique un gestionnaire étonnamment général
Un bloc de lecture de fichier intercepte
Exceptionet affiche « Problème de fichier ». Il échoue en réalité avec uneNullPointerExceptioncausée par un bogue. Le gestionnaire la recevra-t-il et ce message est-il fiable ?---reveal---
Oui :
NullPointerExceptionétendRuntimeException, qui étendException. Le message est trompeur car cette erreur est un bogue du code et ne prouve pas l’existence d’un problème de fichier. Lis la trace et restreins le gestionnaire prévu aux erreurs qu’il peut expliquer. - 11RécapitulatifChoisis la prochaine action de débogage
Commence l’étude d’une erreur par sa classe, son message et le premier cadre de l’application. Suis les appelants et l’origine des valeurs incorrectes lorsque l’instruction détectée ne suffit pas à expliquer la cause.
Vérifie ensuite l’héritage avant de choisir une gestion : les erreurs contrôlées exigent une décision visible par le compilateur ; les bogues non contrôlés doivent tout de même être corrigés. Évite que des gestionnaires généraux présentent un type de problème comme un autre.
2Suis les chemins de reprise et de nettoyage
12 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionDécide de ce qui doit se passer ensuite
- 2ExempleReprends après l’ensemble de l’instruction
- 3ConseilLis un nouveau texte à chaque tentative
- 4DéfiCorrige le scanner bloqué
- 5ExplicationDonne une réponse propre à une erreur précise
- 6ExempleLaisse la boucle continuer
- 7DéfiDéplace la limite de la région protégée
- 8Point cléPartage les réponses sans chevauchement des types
- 9ExplicationLe nettoyage s’exécute avant la sortie
- 10DéfiSuis une erreur sans gestionnaire correspondant
- 11DéfiEmpêche le nettoyage de masquer une erreur à réessayer
- 12RécapitulatifTrouve la prochaine instruction accessible
3Rejette une demande sans endommager l’état
11 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionPréserve un objet utilisable
- 2ExempleValide avant la soustraction
- 3ExplicationDistingue throw de la déclaration
- 4DéfiChoisis l’exception standard adaptée
- 5LienUne redéfinition respecte les engagements pris envers les appelants
- 6ExempleDonne un type propre au stock insuffisant
- 7ExempleGarde la demande échouée distincte
- 8DéfiDétermine l’état qui subsiste
- 9ExplicationConserve l’erreur de conversion d’origine
- 10DéfiTransmets une erreur de fichier par une méthode soumise à une restriction
- 11RécapitulatifConçois une exception utilisable par l’appelant
4Ouvre le bon fichier texte et ferme-le correctement
12 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionL’emplacement et la durée de vie comptent tous deux
- 2ExempleRésous le chemin à partir du répertoire de travail
- 3ExplicationDécode avec le jeu de caractères utilisé à l’écriture
- 4ConseilRetire une fin de ligne complète
- 5DéfiConserve un nombre décimal lors de l’écriture et de la relecture
- 6ExplicationDéclare une ressource à fermer
- 7LienUtilise le contrat de fermeture
- 8ExempleInverse l’ordre d’ouverture
- 9DéfiSuis l’échec d’une deuxième ouverture
- 10Point cléGarde l’erreur du corps comme erreur principale
- 11DéfiDistingue l’erreur de données de l’erreur de nettoyage
- 12RécapitulatifExamine une opération sur un fichier dans l’ordre
5Transforme des mesures en un rapport fiable
16 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionUn rapport exige plus qu’un calcul correct
- 2ExplicationChoisis comment les lignes sont lues
- 3ExempleDéfinis l’enregistrement avant l’analyse
- 4ExempleValide avant d’utiliser le deuxième champ
- 5DéfiLocalise l’enregistrement rejeté
- 6ExplicationChoisis entre remplacer et ajouter à la fin
- 7ExempleÉcris une ligne de rapport portable
- 8ConseilRepère une écriture qui a échoué
- 9DéfiConserve les anciennes et les nouvelles entrées du journal
- 10LienReprends l’exécution à deux niveaux différents
- 11ExempleNe mets à jour les sommes qu’après validation
- 12DéfiGère une valeur analysable mais inutilisable
- 13ExplicationTermine la sortie avant de remplacer la cible
- 14ConseilGarde l’erreur d’enregistrement visible
- 15DéfiDétermine ce qui peut être rapporté de façon fiable
- 16RécapitulatifExamine le programme de traitement selon les chemins d’erreur
Exceptions et fichiers en Java : QCM
Série 1 : Suis les erreurs et choisis une reprise utile10 Questions Pratiques
Question 1 sur 10
values[5] ?Afficher la réponseMasquer la réponse
ArrayIndexOutOfBoundsException lors de cet accès. Compter cinq éléments ne rend pas l’indice 5 valide : le cinquième élément est à l’indice 4.Question 2 sur 10
DataProblem étend directement Exception. Quelle obligation une méthode a-t-elle lorsqu’elle appelle une méthode auxiliaire déclarée avec throws DataProblem ?Afficher la réponseMasquer la réponse
DataProblem est contrôlée car elle étend Exception hors de la branche RuntimeException. Le code appelant doit l’intercepter ou déclarer un type contrôlé applicable. Le compilateur vérifie la possibilité déclarée, même si un appel particulier réussissait.Question 3 sur 10
Quelles lettres s’affichent, dans l’ordre ?
System.out.print("P");
try {
int n = Integer.parseInt("7q");
System.out.print("Q");
} catch (NumberFormatException e) {
System.out.print("R");
}
System.out.print("S");
Afficher la réponseMasquer la réponse
NumberFormatException avant l’instruction qui affiche Q. Le gestionnaire correspondant affiche R, puis l’exécution continue après l’instruction et affiche S. L’instruction ignorée ne s’exécute pas après la reprise ; PQRS ne peut donc pas être la sortie.Question 4 sur 10
NoSuchFileException ou une autre IOException. Quel ordre de clauses catch donne à chacune sa propre réponse ?Afficher la réponseMasquer la réponse
NoSuchFileException étend IOException ; son gestionnaire spécifique doit donc apparaître en premier. Placer IOException d’abord intercepterait déjà toutes les exceptions de fichier manquant et rendrait le gestionnaire suivant inaccessible. Une capture multiple ne peut pas non plus combiner ces types liés.Question 5 sur 10
Qu’affiche et que renvoie l’appel de pick() ?
static int pick() {
try {
return 8;
} finally {
System.out.print("done");
}
}
Afficher la réponseMasquer la réponse
finally avant de transmettre cette valeur à son appelant. Elle affiche donc done et renvoie 8. Un retour dans try ne contourne pas le nettoyage ; seul un transfert de contrôle concurrent depuis le nettoyage remplacerait ce résultat.Question 6 sur 10
Afficher la réponseMasquer la réponse
IllegalArgumentException décrit donc l’erreur. IllegalStateException décrirait un appel interdit par l’état actuel de l’objet. Aucune opération d’analyse n’est mentionnée : un argument numérique seul ne fait donc pas de cette erreur un problème de format numérique.Question 7 sur 10
/work/app comme répertoire de travail. Il crée Path.of("data", "levels.txt"). Quel emplacement absolu ce chemin relatif désigne-t-il ?Afficher la réponseMasquer la réponse
/work/app pour donner /work/app/data/levels.txt. Java n’insère pas de dossier source. Placer le fichier à côté du code source ne fonctionnerait que si cet emplacement correspondait à celui désigné par le chemin résolu.Question 8 sur 10
a s’ouvre, mais l’ouverture de la ressource b lève une exception. Les deux sont déclarées dans cet ordre dans le même en-tête d’instruction try avec gestion des ressources. La fermeture de a lève aussi une exception. Quelle erreur atteint l’appelant ?Afficher la réponseMasquer la réponse
b échoue, Java ferme quand même a, déjà ouvert. L’erreur d’ouverture reste principale et l’erreur de fermeture ultérieure lui est rattachée comme exception supprimée. Choisir l’erreur de fermeture comme principale revient à confondre l’instruction try avec gestion des ressources avec un nettoyage manuel qui peut écraser une erreur antérieure.Question 9 sur 10
BufferedReader a atteint la fin de son fichier. Que renvoie le prochain appel à readLine() ?Afficher la réponseMasquer la réponse
BufferedReader.readLine() renvoie null lorsqu’il ne reste aucun caractère pour former une autre ligne. Une chaîne vide représente une véritable ligne blanche ; l’utiliser comme marqueur de fin arrêterait donc la lecture trop tôt. Les terminateurs de ligne sont retirés des lignes renvoyées et ne constituent pas un marqueur de fin de fichier.Question 10 sur 10
Files.writeString de conserver le texte existant et d’ajouter du texte à la fin ?Afficher la réponseMasquer la réponse
APPEND écrit après le contenu existant et CREATE permet de créer un fichier manquant. Utiliser seulement APPEND échoue lorsque le journal n’existe pas. TRUNCATE_EXISTING effacerait le contenu existant, tandis que CREATE_NEW rejette un chemin qui existe déjà.Série 2 : Applique les contrats aux enregistrements et à la sortie de fichiers10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
Une trace commence par ces cadres. Quelle ligne de ta classe dois-tu examiner en premier ?
java.lang.NumberFormatException: For input string: "six"
at java.base/java.lang.NumberFormatException.forInputString(...)
at java.base/java.lang.Integer.parseInt(...)
at Importer.readCount(Importer.java:18)
at Importer.main(Importer.java:6)
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
AmountProblem étend IllegalArgumentException. Comment est-elle classée ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
InputMismatchException de Scanner.nextInt(), affiche un message et rappelle immédiatement nextInt(). Le prochain jeton est "many". Pourquoi la boucle continue-t-elle d’échouer ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
void load() throws IOException. Une implémentation doit déclarer une erreur de fichier manquant. Quelle déclaration contrôlée est autorisée dans sa méthode redéfinie ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
remove rejette les demandes supérieures au stock actuel avant de modifier la Map. Des appels en retirent 6, puis en demandent 14 ; la deuxième erreur est encapsulée avec sa cause et interceptée par l’appelant. Quel stock et quelles informations de diagnostic subsistent ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
Double.parseDouble("6,25") s’exécute sur un ordinateur utilisant des paramètres régionaux allemands ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
line.split(",") et line.split(",", -1) ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
PrintWriter, mais un disque plein empêche l’enregistrement du texte. Que doit-il utiliser pour détecter l’erreur enregistrée par l’objet d’écriture ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Série 3 : Suis les interactions entre erreurs et nettoyage10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
NumberFormatException lorsqu’un gestionnaire de superclasse l’intercepte ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
Quelle valeur est affichée ?
int count;
try {
count = Integer.parseInt("bad");
} catch (NumberFormatException e) {
count = 4;
}
System.out.println(count + 2);
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
Quelle valeur est affichée à la fin ?
int total = 0;
try {
for (String text : new String[] {"8", "bad", "3"}) {
try {
total += Integer.parseInt(text);
} catch (NumberFormatException e) {
throw new IllegalStateException("record", e);
}
}
} catch (IllegalStateException e) {
total += 2;
}
System.out.println(total);
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
Que fait result() ?
static int result() {
try {
throw new IllegalArgumentException("bad");
} finally {
return 9;
}
}
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
NumberFormatException e. Sa classe personnalisée InvalidRecordException possède des constructeurs acceptant un message seul ou un message et une cause. Comment doit-il ajouter "Line 8" tout en conservant la trace d’origine ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
Files.readString(path).split("\n"), puis Integer.parseInt sur chaque fragment non vide. Pourquoi la conversion d’un fragment contenant les chiffres "27" peut-elle échouer ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
a et b s’ouvrent correctement dans cet ordre. Le corps lève E ; la fermeture de b lève F ; la fermeture de a lève G. Que reçoit la clause catch associée à cette instruction try avec gestion des ressources ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
Files.exists, puis lue avec un scanner. Sa boucle se termine après seulement quelques enregistrements car le lecteur sous-jacent a échoué, et le programme commence immédiatement l’enregistrement. Que faut-il changer pour éviter de considérer cette entrée partielle comme une réussite ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Série 4 : Diagnostique et améliore un programme de traitement complet10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
Que s’affiche-t-il avant que l’exception quitte main, et quel est le premier cadre de l’application dans sa trace ?
public class Counter {
static int read() {
return Integer.parseInt("9z");
}
static void show() {
System.out.print("L");
System.out.print(read());
System.out.print("M");
}
public static void main(String[] args) {
show();
System.out.print("N");
}
}
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
catch (NumberFormatException | IllegalArgumentException e). Pourquoi cette capture multiple ne compile-t-elle pas ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
Qu’affiche et que renvoie choose() ?
static int choose() {
int value = 5;
try {
return value;
} finally {
value = 12;
System.out.print(value);
}
}
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
ReaderTask déclare String read() throws IOException. La classe FixedTask l’implémente avec public String read() sans déclaration contrôlée. La variable task est de type ReaderTask et référence un FixedTask. Que doit faire le code qui appelle task.read() ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
IOException. Quelle classe d’encapsulation standard conserve cette cause tout en exposant une erreur non contrôlée ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
close() lève ensuite IOException, et la clause catch associée renvoie 2 ; son bloc finally affiche "closed" sans lever d’exception. Que fait la méthode ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
Double.parseDouble sur des ordinateurs utilisant n’importe quels paramètres régionaux. Quelle méthode d’écriture respecte ce format ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Tu bloques sur ton propre exercice ? Aide aux Devoirs
Mots-Clés
A
Ajout en fin de fichier
Analyse syntaxique
ArithmeticException
ArithmeticException lors de la division.AutoCloseable
AutoCloseable peut afficher son nom lorsque le nettoyage automatique appelle close().B
Bloc finally
return atteigne l’appelant.Bloc try
BufferedReader
BufferedReader traite une entrée volumineuse jusqu’à ce que readLine() renvoie null à la fin.BufferedWriter
BufferedWriter écrit une ligne de rapport puis utilise newLine() pour ajouter la fin de ligne du système.C
Capture multiple
Cause
InvalidRecordException peut être la NumberFormatException levée par son champ numérique.Chaînage d’exceptions
Champ
Chemin absolu
toAbsolutePath() montre le chemin absolu utilisé pour diagnostiquer un fichier placé dans le mauvais dossier.Chemin relatif
data/counts.txt peut désigner un autre fichier lorsque le programme démarre dans un autre dossier.Clause catch
NumberFormatException peut demander un autre nombre après la saisie de "many" par l’utilisateur.Clause throws
throws IOException permet à une méthode auxiliaire de fichier de signaler une erreur à un appelant capable de reprendre l’exécution.Closeable
BufferedReader implémente Closeable ; il peut donc être déclaré dans une instruction try avec gestion des ressources.CSV
D
Déplacement atomique
E
Encodage des caractères
Erreur au niveau d’un enregistrement
Erreur au niveau du fichier entier
Error
OutOfMemoryError appartient à Error ; intercepter une saisie ordinaire invalide ne résout pas un épuisement du tas.Exception
Exception contrôlée
IOException est une exception contrôlée ; une méthode auxiliaire de lecture de fichier doit donc l’intercepter ou la déclarer.Exception non contrôlée
Exception personnalisée
Exception supprimée
É
Échec immédiat
F
Fichier temporaire
Fin de ligne
BufferedReader.readLine() est retirée avant que la méthode renvoie le texte de la ligne.G
Gestionnaire inaccessible
IOException en premier crée un gestionnaire inaccessible si NoSuchFileException est interceptée ensuite.H
Hiérarchie des exceptions
I
IllegalArgumentException
IllegalArgumentException lorsque la quantité positive requise lui est fournie sous la forme -2.IllegalStateException
IllegalStateException lorsque le code tente d’y ajouter un autre article.InputMismatchException
nextInt() lève InputMismatchException sur "several" et laisse ce jeton disponible pour être écarté.Instruction try avec gestion des ressources
L
Ligne d’en-tête
M
Masquage d’exception
finally peut provoquer un masquage d’exception en écartant une erreur levée dans le bloc try.N
Nettoyage
NullPointerException
name.trim() lorsque name vaut null lève NullPointerException avant le renvoi de tout texte débarrassé des caractères blancs autour.NumberFormatException
Integer.parseInt("blue") lève NumberFormatException car le texte ne peut pas représenter un entier.O
Ordre des clauses catch
NoSuchFileException avant IOException lorsque chacune nécessite un message distinct.P
Paramètres régionaux
Path
Path.of("data", "counts.txt") construit un Path sans vérifier si le dossier de données existe.Pile d’appels
main appelle load, qui appelle parse, la pile d’appels enregistre les trois appels de méthodes actifs.PrintWriter
PrintWriter peut formater une moyenne avec printf, mais le retour normal de cet appel ne prouve pas que l’enregistrement a réussi.Propagation
R
Région protégée
Règle de capture ou de déclaration
Files.readString, même lorsque le fichier qu’elle lit existe.Répertoire de travail
/work/app comme répertoire de travail, data/counts.txt désigne un fichier dans /work/app/data.Reprise après erreur
Ressource
Retour en attente
finally ne réévalue pas l’expression d’un retour en attente.RuntimeException
NumberFormatException atteint RuntimeException par sa superclasse IllegalArgumentException.S
Scanner
Scanner de fichier nécessite une vérification de ioException() après sa boucle pour qu’une lecture échouée ne paraisse pas réussie.T
Tampon
throw
throw avant l’affectation à un champ rejette une capacité invalide tout en conservant l’ancienne valeur du champ.Throwable
Throwable par l’intermédiaire de Exception ; Java peut donc la lever et l’intercepter.Trace de pile
Troncature
Files.writeString provoque une troncature par défaut ; une erreur d’écriture ultérieure peut donc laisser un résultat incomplet.U
UncheckedIOException
IOException peut transmettre une erreur de fichier avec UncheckedIOException.UTF-8
V
Vidage du tampon
- 1Premiers programmes Java
- 2Conditions et boucles en Java
- 3Méthodes Java
- 4Listes et tableaux en Java
- 5Classes et objets en Java
- 6Références et égalité en Java
- 7HashMap et collections en Java
- 8Héritage et polymorphisme en Java
- 9Exceptions et fichiers en Java
- 10Paquetages et tests unitaires Java
- 11Généricité et flux en Java
À propos de cette unité
Crée ton propre Matériel d'Étude
Transforme tes notes, diapos et documents en Guides d'Étude, Questions Pratiques, Flashcards et 6 autres outils.