Exceptions et fichiers en Java

Découvre comment Java signale les problèmes pendant l’exécution d’un programme et comment les traiter. Lis des traces de pile, distingue les exceptions contrôlées des exceptions non contrôlées et gère les erreurs avec 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

  1. 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 pile
      Explique 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ées
      Situe 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.
  2. 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 ordre
      Utilise 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 finally
      Ajoute 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.
  3. 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 throws
      Valide 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.
  4. 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 ligne
      Construis 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 ressources
      Utilise 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.
  5. 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ées
      Lis 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 fichiers
      Combine 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.

Exceptions et fichiers en Java : cours

5 chapitres

1

Comprends 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.

ExceptionDéclencheur typique
ArithmeticExceptionDivision entière par zéro
ArrayIndexOutOfBoundsExceptiona[3] lorsque le tableau est de longueur 3
IndexOutOfBoundsExceptionlist.get(list.size())
NullPointerExceptionAppel d’une méthode par une référence null
NumberFormatExceptionInteger.parseInt("12a")
InputMismatchExceptionScanner.nextInt() rencontre "ten"
ClassCastExceptionTranstypage 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)
  1. Lis la première ligne pour connaître la classe et le message de l’exception.
  2. Lis le premier cadre at pour trouver où le problème a été détecté.
  3. Descends pour trouver les appelants : main a appelé average à la ligne 9.
  4. Si les premiers cadres appartiennent à la bibliothèque Java, trouve le premier cadre qui nomme ta propre classe. Pour un appel à Integer.parseInt qui é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égorieClassesExigence du compilateur
Non contrôléesRuntimeException, Error et leurs sous-classesLa capture ou la déclaration est facultative
ContrôléesToutes les autres sous-classes de ThrowableLes 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, Error et toutes leurs sous-classes sont non contrôlées.
  • Les autres sous-classes de Throwable sont 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 Exception peut masquer des bogues de programmation.
  • Classe une exception inconnue à partir de sa chaîne de superclasses.
2

Gè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 try ayant é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

  • finally s’exécute après une fin normale, des exceptions interceptées ou non interceptées et des transferts de contrôle comme return.
  • Une expression de retour est évaluée avant l’exécution du nettoyage.
  • Le code après une instruction try est ignoré lorsqu’une exception se propage ; finally est tout de même atteint.
  • Un retour ou une exception levée dans finally peut 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.
3

Lè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èmeException standard
Un argument a une valeur invalideIllegalArgumentException
L’état de l’objet ne permet pas l’appelIllegalStateException
Une référence d’objet obligatoire vaut nullNullPointerException
La classe ne propose pas l’opérationUnsupportedOperationException
L’indice est hors d’une collectionIndexOutOfBoundsException

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 throw avec un objet exception pour arrêter une opération invalide.
  • Valide les données avant de modifier les champs ou les collections.
  • throws dé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 Exception pour une classe contrôlée ou RuntimeException pour 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.
  • UncheckedIOException transmet une IOException sous forme d’erreur non contrôlée.
4

Localise 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
ConventionSé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 Path n’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.parseDouble utilise 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 AutoCloseable peuvent ê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.
5

Lis 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éthodeRé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 CREATE avec APPEND pour conserver l’ancien contenu et permettre la création d’un journal.
  • La fermeture vide le tampon de sortie et libère la ressource.
  • PrintWriter enregistre les erreurs d’écriture ; checkError() permet de les détecter.
  • BufferedWriter et les méthodes Files propagent les erreurs d’entrée-sortie.
  • Utilise UTF-8 et Locale.ROOT pour é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

5 Leçons Interactives

1

Remonte d’une erreur à sa cause

11 étapes
Lis une trace d’exception, relie-la aux appels actifs et utilise l’héritage pour classer l’erreur.
  1. 1
    IntroductionUn 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.

  2. 2
    ExempleObserve l’arrêt de la conversion

    Une méthode loadCount exécute ces instructions :

    System.out.print("start ");
    int count = Integer.parseInt("eight");
    System.out.print("finish");
    

    Elle affiche start , puis lève NumberFormatException. L’affectation ne se termine pas et finish est ignoré. Un gestionnaire correspondant peut prendre le relais, mais l’instruction qui a échoué ne reprend pas après la gestion de l’erreur.

  3. 3
    ExplicationSuis les appels actifs

    Supposons que main ait 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, loadCount ne peut pas terminer son travail normal et l’appelant a la possibilité de gérer l’erreur. Si elle sort de main sans être gérée, Java signale l’exception et le thread principal se termine.

  4. 4
    ExempleTrouve 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ù loadCount a é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.

  5. 5
    DéfiTrouve la sortie ignorée

    Une méthode auxiliaire affiche A, appelle Integer.parseInt("q2"), puis afficherait B. Son appelant intercepte NumberFormatException et affiche C. Quelles lettres s’affichent et pourquoi ?

    ---reveal---

    A puis C. La conversion lève une exception avant B ; 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 afficher B.

  6. 6
    ConseilCherche 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 et printStackTrace() pour la chaîne d’appels. Un message peut être null ; une section Caused by: fournit une autre exception conservée dans une exception qui l’encapsule.

  7. 7
    ExplicationUtilise la chaîne de superclasses

    Throwable est la classe de base des objets qui peuvent être levés. Ses branches principales sont Error et Exception ; RuntimeException se trouve sous Exception.

    RuntimeException, Error et toutes leurs sous-classes sont non contrôlées. Les autres sous-classes de Throwable sont 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.

  8. 8
    ExempleCompare un analyseur et un lecteur de fichier

    NumberFormatException étend IllegalArgumentException, qui étend RuntimeException ; un appel à Integer.parseInt n’a donc pas de gestionnaire obligatoire.

    IOException étend Exception hors de cette branche. Un appel à Files.readString doit intercepter l’éventuelle IOException ou la déclarer avec throws. Une erreur de fichier peut avoir des causes externes même lorsque le code appelant est correct.

  9. 9
    DéfiClasse une erreur inconnue

    BadRecordException étend directement Exception. 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.

  10. 10
    DéfiExplique un gestionnaire étonnamment général

    Un bloc de lecture de fichier intercepte Exception et affiche « Problème de fichier ». Il échoue en réalité avec une NullPointerException causée par un bogue. Le gestionnaire la recevra-t-il et ce message est-il fiable ?

    ---reveal---

    Oui : NullPointerException étend RuntimeException, qui étend Exception. 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.

  11. 11
    Ré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.

2

Suis les chemins de reprise et de nettoyage

12 étapes
Suis l’échec d’une conversion de saisie, choisis la portée et l’ordre des gestionnaires et suis l’exécution de finally lors des sorties anticipées.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionDécide de ce qui doit se passer ensuite
  2. 2
    ExempleReprends après l’ensemble de l’instruction
  3. 3
    ConseilLis un nouveau texte à chaque tentative
  4. 4
    DéfiCorrige le scanner bloqué
  5. 5
    ExplicationDonne une réponse propre à une erreur précise
  6. 6
    ExempleLaisse la boucle continuer
  7. 7
    DéfiDéplace la limite de la région protégée
  8. 8
    Point cléPartage les réponses sans chevauchement des types
  9. 9
    ExplicationLe nettoyage s’exécute avant la sortie
  10. 10
    DéfiSuis une erreur sans gestionnaire correspondant
  11. 11
    DéfiEmpêche le nettoyage de masquer une erreur à réessayer
  12. 12
    RécapitulatifTrouve la prochaine instruction accessible
3

Rejette une demande sans endommager l’état

11 étapes
Valide une opération sur un stock, expose une erreur propre au domaine et encapsule une erreur d’analyse en conservant sa cause.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionPréserve un objet utilisable
  2. 2
    ExempleValide avant la soustraction
  3. 3
    ExplicationDistingue throw de la déclaration
  4. 4
    DéfiChoisis l’exception standard adaptée
  5. 5
    LienUne redéfinition respecte les engagements pris envers les appelants
  6. 6
    ExempleDonne un type propre au stock insuffisant
  7. 7
    ExempleGarde la demande échouée distincte
  8. 8
    DéfiDétermine l’état qui subsiste
  9. 9
    ExplicationConserve l’erreur de conversion d’origine
  10. 10
    DéfiTransmets une erreur de fichier par une méthode soumise à une restriction
  11. 11
    RécapitulatifConçois une exception utilisable par l’appelant
4

Ouvre le bon fichier texte et ferme-le correctement

12 étapes
Résous un chemin, fais correspondre les conventions de texte, puis suis l’ouverture et la fermeture des ressources ainsi que les erreurs concurrentes.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionL’emplacement et la durée de vie comptent tous deux
  2. 2
    ExempleRésous le chemin à partir du répertoire de travail
  3. 3
    ExplicationDécode avec le jeu de caractères utilisé à l’écriture
  4. 4
    ConseilRetire une fin de ligne complète
  5. 5
    DéfiConserve un nombre décimal lors de l’écriture et de la relecture
  6. 6
    ExplicationDéclare une ressource à fermer
  7. 7
    LienUtilise le contrat de fermeture
  8. 8
    ExempleInverse l’ordre d’ouverture
  9. 9
    DéfiSuis l’échec d’une deuxième ouverture
  10. 10
    Point cléGarde l’erreur du corps comme erreur principale
  11. 11
    DéfiDistingue l’erreur de données de l’erreur de nettoyage
  12. 12
    RécapitulatifExamine une opération sur un fichier dans l’ordre
5

Transforme des mesures en un rapport fiable

16 étapes
Lis et valide des enregistrements simples, calcule les résultats acceptés et enregistre la sortie complète avec une gestion claire des erreurs.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionUn rapport exige plus qu’un calcul correct
  2. 2
    ExplicationChoisis comment les lignes sont lues
  3. 3
    ExempleDéfinis l’enregistrement avant l’analyse
  4. 4
    ExempleValide avant d’utiliser le deuxième champ
  5. 5
    DéfiLocalise l’enregistrement rejeté
  6. 6
    ExplicationChoisis entre remplacer et ajouter à la fin
  7. 7
    ExempleÉcris une ligne de rapport portable
  8. 8
    ConseilRepère une écriture qui a échoué
  9. 9
    DéfiConserve les anciennes et les nouvelles entrées du journal
  10. 10
    LienReprends l’exécution à deux niveaux différents
  11. 11
    ExempleNe mets à jour les sommes qu’après validation
  12. 12
    DéfiGère une valeur analysable mais inutilisable
  13. 13
    ExplicationTermine la sortie avant de remplacer la cible
  14. 14
    ConseilGarde l’erreur d’enregistrement visible
  15. 15
    DéfiDétermine ce qui peut être rapporté de façon fiable
  16. 16
    RécapitulatifExamine le programme de traitement selon les chemins d’erreur

Exceptions et fichiers en Java : QCM

40 Questions Pratiques en 4 séries

Série 1 : Suis les erreurs et choisis une reprise utile10 Questions Pratiques

Question 1 sur 10

Un tableau est de longueur 5. Que se passe-t-il lorsque le programme évalue values[5] ?
  1. Il lit le cinquième élément du tableau.
  2. Il lève ArrayIndexOutOfBoundsException.
  3. Il renvoie la valeur entière par défaut 0.
  4. Il lève NumberFormatException.
Afficher la réponseMasquer la réponse
Réponse : B
Un tableau de longueur 5 possède les indices valides de 0 à 4 ; l’indice 5 est donc hors du tableau. Java lève 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 ?
  1. Intercepter RuntimeException ou la déclarer.
  2. La déclarer uniquement si la méthode auxiliaire échoue.
  3. La gérer uniquement pendant l’exécution du programme.
  4. Intercepter DataProblem ou la déclarer.
Afficher la réponseMasquer la réponse
Réponse : D
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");
  1. PRS
  2. PQRS
  3. PR
  4. PS
Afficher la réponseMasquer la réponse
Réponse : A
La conversion de "7q" lève 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

Un bloc peut lever NoSuchFileException ou une autre IOException. Quel ordre de clauses catch donne à chacune sa propre réponse ?
  1. IOException, puis NoSuchFileException.
  2. Exception, puis NoSuchFileException.
  3. NoSuchFileException, puis IOException.
  4. IOException | NoSuchFileException dans une seule clause.
Afficher la réponseMasquer la réponse
Réponse : C
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");
    }
}
  1. Il renvoie 8 sans rien afficher.
  2. Il affiche done et renvoie 8.
  3. Il affiche done et ne renvoie aucune valeur.
  4. Il affiche 8, puis renvoie done.
Afficher la réponseMasquer la réponse
Réponse : B
L’expression de retour est évaluée, mais la méthode exécute 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

Une méthode rejette une capacité négative avant de l’affecter à un champ. Quelle exception standard décrit le mieux l’argument invalide ?
  1. IllegalArgumentException
  2. IllegalStateException
  3. NumberFormatException
  4. UnsupportedOperationException
Afficher la réponseMasquer la réponse
Réponse : A
Une capacité négative ne respecte pas la règle de la méthode concernant son argument ; 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

Un programme démarre avec /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 ?
  1. /work/data/levels.txt
  2. /data/levels.txt
  3. /work/app/src/data/levels.txt
  4. /work/app/data/levels.txt
Afficher la réponseMasquer la réponse
Réponse : D
Un chemin relatif part du répertoire de travail ; les deux éléments prolongent donc /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

La ressource 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 ?
  1. L’erreur de fermeture, avec celle d’ouverture supprimée.
  2. L’erreur d’ouverture, avec celle de fermeture écartée.
  3. L’erreur d’ouverture, avec celle de fermeture supprimée.
  4. Les deux erreurs séparément, dans leur ordre d’apparition.
Afficher la réponseMasquer la réponse
Réponse : C
Lorsque l’ouverture de 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

Un BufferedReader a atteint la fin de son fichier. Que renvoie le prochain appel à readLine() ?
  1. null
  2. Une chaîne vide.
  3. Une chaîne contenant "EOF".
  4. Une chaîne contenant "\n".
Afficher la réponseMasquer la réponse
Réponse : A
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

Un journal UTF-8 peut déjà exister ou être absent. Quelles options permettent à Files.writeString de conserver le texte existant et d’ajouter du texte à la fin ?
  1. CREATE et TRUNCATE_EXISTING
  2. CREATE et APPEND
  3. APPEND sans CREATE
  4. CREATE_NEW et WRITE
Afficher la réponseMasquer la réponse
Réponse : B
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)
  1. La ligne 6 de Importer.main.
  2. Le cadre de bibliothèque dans forInputString.
  3. La ligne 18 de Importer.readCount.
  4. La ligne après la ligne 18 de Importer.
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 ?
  1. Non contrôlée, par RuntimeException.
  2. Contrôlée, car c’est une classe personnalisée.
  3. Contrôlée, car sa classe parente est une exception.
  4. Non contrôlée, par la branche Error.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Une boucle de nouvelle tentative intercepte l’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 ?
  1. Le gestionnaire rembobine tout le flux d’entrée.
  2. Le scanner convertit le jeton en zéro.
  3. L’exception ferme définitivement le scanner.
  4. La lecture échouée laisse le même jeton non lu.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Une interface déclare 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 ?
  1. throws Exception
  2. throws NoSuchFileException
  3. throws Throwable
  4. throws InterruptedException
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Un stock contient 17 marqueurs. Sa méthode 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 ?
  1. 11 marqueurs et seulement le nouveau message de l’exception d’encapsulation.
  2. -3 marqueurs et l’erreur d’origine comme cause.
  3. 11 marqueurs et l’erreur d’origine comme cause.
  4. 17 marqueurs et l’erreur d’origine comme cause.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Que se passe-t-il lorsque Double.parseDouble("6,25") s’exécute sur un ordinateur utilisant des paramètres régionaux allemands ?
  1. Elle renvoie la valeur décimale 6,25.
  2. Elle renvoie la valeur entière 625.
  3. Elle lève MalformedInputException.
  4. Elle lève NumberFormatException.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Quelle interface un objet doit-il implémenter pour être déclaré comme ressource dans une instruction try avec gestion des ressources ?
  1. AutoCloseable
  2. Serializable
  3. Iterable
  4. Comparable
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

La ligne est "Nora,". Quelle différence compte entre line.split(",") et line.split(",", -1) ?
  1. Les deux renvoient deux champs, dont un second champ vide.
  2. Le premier garde la virgule ; le second la supprime.
  3. Le premier renvoie un champ ; le second garde un second champ vide.
  4. Le premier lève une exception ; le second renvoie un champ.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Un programme écrit avec 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 ?
  1. Intercepter l’IOException de println lui-même.
  2. Appeler checkError() et examiner le résultat.
  3. Examiner le getFileName() du chemin du fichier.
  4. Supposer que la fermeture garantit l’enregistrement.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Un rapport doit protéger un résultat existant contre un remplacement partiel. La lecture et le calcul sont terminés. Quelle méthode d’enregistrement convient ?
  1. Écrire directement sur la cible ; recommencer si la première écriture échoue.
  2. Écrire un fichier temporaire ; utiliser un déplacement non atomique si le déplacement atomique échoue.
  3. Vérifier que la cible existe ; ajouter le nouveau rapport après l’ancien résultat.
  4. Écrire et fermer un fichier temporaire dans le même dossier ; demander un déplacement atomique et signaler un remplacement non pris en charge.
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

Quelle famille d’exceptions reçoit aussi NumberFormatException lorsqu’un gestionnaire de superclasse l’intercepte ?
  1. RuntimeException
  2. IOException
  3. Error
  4. FileNotFoundException
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);
  1. 4
  2. 2
  3. 6
  4. Rien ; count n’est pas initialisée.
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);
  1. 13
  2. 10
  3. 11
  4. 2
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;
    }
}
  1. Elle lève l’exception et ne renvoie jamais 9.
  2. Elle renvoie 9, puis lève l’exception à l’appelant.
  3. Elle ne compile pas, car finally ne peut pas effectuer de retour.
  4. Elle renvoie 9 et écarte l’exception en attente.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Un analyseur intercepte 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 ?
  1. throw new InvalidRecordException(e.getMessage());
  2. throw new InvalidRecordException("Line 8", e);
  3. throw new InvalidRecordException("Line 8");
  4. throw new RuntimeException("Line 8");
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Un fichier texte Windows contient des lignes d’entiers terminées par CRLF. Le code utilise 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 ?
  1. parseInt exige toujours un point décimal.
  2. UTF-8 ne peut pas représenter les fins de ligne Windows.
  3. Le découpage peut laisser un \r à la fin du fragment.
  4. Le découpage transforme automatiquement les chiffres en octets.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Les ressources 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 ?
  1. E, avec F puis G comme erreurs supprimées.
  2. G, avec E puis F comme erreurs supprimées.
  3. F, avec G puis E comme erreurs supprimées.
  4. E seule, car la fermeture s’arrête après F.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Un petit fichier commence par "name,age", suivi de "Omar,36". Pourquoi faut-il traiter la première ligne séparément avant de convertir le champ de l’âge ?
  1. Elle utilise un encodage de caractères différent des données.
  2. Sa virgule empêche split de trouver deux champs.
  3. Un lecteur la renvoie automatiquement comme ligne vide.
  4. Elle nomme les colonnes au lieu de fournir un âge entier.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Un programme de traitement lit "zone,temperature" comme en-tête, puis "north,2.0", "east,bad" et "west,8.0". La règle imposée est d’ignorer les enregistrements incorrects et d’enregistrer un rapport sur les enregistrements valides. Une clause catch entoure actuellement toute la boucle d’analyse. Quelle modification applique cette règle ?
  1. Garder la clause catch à l’extérieur ; reprendre automatiquement la boucle après le gestionnaire.
  2. Écrire chaque somme dans la destination avant d’essayer d’analyser l’enregistrement suivant.
  3. Intercepter les erreurs d’enregistrement dans chaque itération ; enregistrer après la lecture et le calcul.
  4. Renvoyer un résultat vide depuis le lecteur à chaque échec d’analyse.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

L’entrée est vérifiée avec 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 ?
  1. Vérifier ioException() après la lecture et arrêter l’enregistrement si une erreur de lecture est enregistrée.
  2. Répéter Files.exists après la lecture et enregistrer dès que le résultat est vrai.
  3. Intercepter seulement NumberFormatException autour de chaque lecture, puis enregistrer.
  4. Fermer le scanner et supposer que ses lectures précédentes ont couvert tout le fichier.
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");
    }
}
  1. LM ; Counter.show(Counter.java:7).
  2. L seulement ; Counter.main(Counter.java:11).
  3. LMN ; Counter.read(Counter.java:3).
  4. L seulement ; Counter.read(Counter.java:3).
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Un bloc catch signale une saisie numérique invalide, mais continue avec une valeur par défaut affectée précédemment. Quelle condition cette valeur doit-elle remplir pour que la reprise soit utile ?
  1. Elle doit toujours être la valeur entière zéro.
  2. Elle doit être valide pour la suite du calcul.
  3. Elle doit être égale au texte dont la conversion a échoué.
  4. Elle doit être affectée dans l’instruction qui a échoué.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Un analyseur utilise catch (NumberFormatException | IllegalArgumentException e). Pourquoi cette capture multiple ne compile-t-elle pas ?
  1. Aucun des deux types n’est une exception contrôlée.
  2. Les deux types exigent des noms de variables différents.
  3. L’un des types est une sous-classe de l’autre.
  4. La capture multiple n’autorise que les erreurs de fichier.
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);
    }
}
  1. Elle affiche 12 et renvoie 5.
  2. Elle affiche 12 et renvoie 12.
  3. Elle affiche 5 et renvoie 5.
  4. Elle n’affiche rien et renvoie 12.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

L’interface 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() ?
  1. Omettre la gestion car l’implémentation ne déclare aucune erreur contrôlée.
  2. Intercepter RuntimeException au lieu du type contrôlé déclaré.
  3. Ajouter throws IOException à l’implémentation avant de l’appeler.
  4. Intercepter ou déclarer IOException selon la déclaration de l’interface.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Une méthode redéfinie n’est pas autorisée à ajouter des exceptions contrôlées, mais elle appelle du code de fichier qui peut lever IOException. Quelle classe d’encapsulation standard conserve cette cause tout en exposant une erreur non contrôlée ?
  1. new IOException(e.getMessage())
  2. new UncheckedIOException(e)
  3. new Exception(e)
  4. new RuntimeException("error")
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Le corps d’une instruction avec gestion des ressources renvoie 6. Sa méthode 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 ?
  1. Elle affiche closed et renvoie 2.
  2. Elle affiche closed et renvoie 6.
  3. Elle lève IOException et ne renvoie aucune valeur.
  4. Elle renvoie 6 sans entrer dans la clause catch.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Un fichier contient l’en-tête "label,count", puis "oak,7", "ash,", "elm,11" et "fir,x". Le programme de traitement ignore l’en-tête, conserve les champs vides après découpage, valide les deux champs et intercepte les erreurs d’enregistrement dans la boucle. Quels sont l’effectif valide, la somme et les numéros des lignes physiques rejetées ?
  1. 3 enregistrements, somme 18 ; seule la ligne 5 est rejetée.
  2. 1 enregistrement, somme 7 ; lignes 3, 4 et 5 rejetées.
  3. 2 enregistrements, somme 18 ; lignes 3 et 5 rejetées.
  4. 2 enregistrements, somme 18 ; lignes 2 et 4 rejetées.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Un fichier de données UTF-8 doit contenir une ligne "sample,7.50", dont le second champ est lisible avec Double.parseDouble sur des ordinateurs utilisant n’importe quels paramètres régionaux. Quelle méthode d’écriture respecte ce format ?
  1. Écrire "sample," + String.format("%.2f", 7.5) et une fin de ligne.
  2. Écrire "sample," + String.format(Locale.ROOT, "%.2f", 7.5) et une fin de ligne.
  3. Écrire "sample," + String.format(Locale.GERMANY, "%.2f", 7.5) et une fin de ligne.
  4. Écrire "sample," + Integer.toString((int) 7.5) et une fin de ligne.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Un programme de traitement lit un en-tête valide et trois enregistrements invalides. Il doit rapporter les données acceptées et les enregistrements ignorés, et protéger un rapport existant contre un remplacement partiel. Quels résultat et ordre d’enregistrement conviennent ?
  1. Indiquer aucune mesure valide et trois lignes ignorées ; déplacer la sortie temporaire vers la cible avant de fermer l’objet d’écriture.
  2. Indiquer aucune mesure valide et quatre lignes ignorées ; fermer la sortie temporaire et demander un remplacement atomique.
  3. Indiquer aucune mesure valide et trois lignes ignorées ; remplacer directement la cible, puis vider le tampon et fermer l’objet d’écriture.
  4. Indiquer aucune mesure valide et trois lignes ignorées ; fermer la sortie temporaire et demander un remplacement atomique.
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

64 Mots-Clés, chacun avec sa définition

A

Ajout en fin de fichier
L’ajout en fin de fichier place une nouvelle sortie à la fin d’un fichier existant tout en conservant les caractères qui y sont déjà stockés.
L’ajout d’une entrée de journal conserve les entrées précédentes, mais n’insère pas de séparateur manquant avant le nouveau texte.
Analyse syntaxique
L’analyse syntaxique interprète du texte selon une structure attendue et convertit les champs en valeurs ou en objets utilisables par le programme.
L’analyse syntaxique d’un enregistrement contenant un nom et un âge vérifie ses deux champs avant de convertir l’âge et de construire une personne.
ArithmeticException
Une ArithmeticException est une exception non contrôlée indiquant une situation arithmétique exceptionnelle, comme une division entière par zéro.
Calculer une moyenne entière avec un tableau vide peut lever ArithmeticException lors de la division.
AutoCloseable
AutoCloseable est l’interface qui déclare close et permet à un objet d’être fermé automatiquement par une instruction try avec gestion des ressources.
Une classe auxiliaire qui implémente AutoCloseable peut afficher son nom lorsque le nettoyage automatique appelle close().

B

Bloc finally
Un bloc finally contient le code de nettoyage exécuté lorsque le contrôle quitte son instruction try, notamment après un travail normal, un gestionnaire, un retour ou une exception levée.
Le bloc finally affiche un message de nettoyage avant qu’une valeur préparée par return atteigne l’appelant.
Bloc try
Un bloc try encadre un travail dont les exceptions peuvent être gérées par les clauses catch associées ; en cas d’erreur, ses instructions restantes sont ignorées.
Un bloc try qui convertit du texte en entier puis l’affiche s’arrête avant l’instruction d’affichage lorsque la conversion échoue.
BufferedReader
Un BufferedReader lit efficacement une entrée de caractères à l’aide d’un tampon et peut renvoyer une ligne à la fois sans sa fin de ligne.
Une boucle avec BufferedReader traite une entrée volumineuse jusqu’à ce que readLine() renvoie null à la fin.
BufferedWriter
Un BufferedWriter écrit une sortie de caractères par l’intermédiaire d’un tampon, prend en charge les fins de ligne et signale les erreurs d’entrée-sortie avec IOException.
Un BufferedWriter écrit une ligne de rapport puis utilise newLine() pour ajouter la fin de ligne du système.

C

Capture multiple
Une capture multiple est une clause catch qui réunit des types d’exceptions sans lien entre eux avec une barre verticale afin qu’ils partagent le même corps de gestionnaire.
Une capture multiple peut signaler un enregistrement mal formé aussi bien pour un champ entier incorrect que pour un élément de tableau manquant.
Cause
Une cause est l’objet pouvant être levé d’origine, conservé dans une exception qui l’encapsule et accessible par getCause pour le diagnostic.
La cause d’une InvalidRecordException peut être la NumberFormatException levée par son champ numérique.
Chaînage d’exceptions
Le chaînage d’exceptions conserve une exception d’origine comme cause d’une nouvelle exception qui ajoute un type ou un contexte de diagnostic plus utile.
Le chaînage d’exceptions ajoute le numéro de ligne de l’enregistrement en échec sans perdre la trace de conversion d’origine.
Champ
Un champ est une valeur d’un enregistrement structuré, comme le nom ou l’âge séparés par une virgule dans une ligne simple de données textuelles.
Le deuxième champ de "Mina," est vide lors d’un découpage avec une limite négative qui conserve les champs vides finaux.
Chemin absolu
Un chemin absolu indique un emplacement à partir de la racine du système de fichiers, y compris celle d’un lecteur si nécessaire, indépendamment du répertoire de travail.
L’appel à toAbsolutePath() montre le chemin absolu utilisé pour diagnostiquer un fichier placé dans le mauvais dossier.
Chemin relatif
Un chemin relatif indique un emplacement à partir du répertoire de travail au lieu de partir de la racine du système de fichiers ou d’un lecteur.
Le chemin relatif data/counts.txt peut désigner un autre fichier lorsque le programme démarre dans un autre dossier.
Clause catch
Une clause catch indique un type d’objet pouvant être levé et un gestionnaire qui s’exécute lorsqu’une exception issue du travail protégé correspond à ce type.
Une clause catch pour NumberFormatException peut demander un autre nombre après la saisie de "many" par l’utilisateur.
Clause throws
Une clause throws fait partie d’une déclaration de méthode, énumère les types d’exceptions qui peuvent en sortir et transmet aux appelants l’obligation de gérer les exceptions contrôlées.
La clause throws throws IOException permet à une méthode auxiliaire de fichier de signaler une erreur à un appelant capable de reprendre l’exécution.
Closeable
Closeable est une sous-interface de AutoCloseable destinée aux ressources d’entrée-sortie, dont la méthode close déclare IOException au lieu du type plus général Exception.
Un BufferedReader implémente Closeable ; il peut donc être déclaré dans une instruction try avec gestion des ressources.
CSV
Le CSV est un format texte de valeurs séparées par des virgules, qui stocke généralement un enregistrement par ligne ; les champs entre guillemets peuvent contenir des virgules et exigent une analyse CSV appropriée.
Un CSV simple contenant "Mina,28" peut être découpé, tandis qu’une virgule entre guillemets dans un nom nécessite un analyseur CSV.

D

Déplacement atomique
Un déplacement atomique change l’emplacement d’un fichier en une seule opération du système de fichiers lorsqu’il est pris en charge ; le remplacement d’une cible existante dépend de l’implémentation.
Un déplacement atomique rend visible le rapport terminé en une seule fois, et un remplacement non pris en charge est signalé comme une erreur d’enregistrement.

E

Encodage des caractères
Un encodage des caractères associe les caractères du texte à des octets stockés et indique comment un lecteur interprète ces octets pour retrouver le texte.
Un encodage des caractères inadapté peut afficher le texte UTF-8 « café » sous une forme altérée comme « café ».
Erreur au niveau d’un enregistrement
Une erreur au niveau d’un enregistrement rend un enregistrement d’entrée inutilisable tout en permettant de traiter les suivants selon une règle qui prévoit de l’ignorer et de le signaler.
Une erreur au niveau d’un enregistrement signale « Line 6: invalid temperature » et laisse l’itération suivante accessible.
Erreur au niveau du fichier entier
Une erreur au niveau du fichier entier empêche une opération sur un fichier de se terminer de façon fiable, comme une entrée manquante ou une erreur de disque pendant l’enregistrement d’un rapport.
Une erreur au niveau du fichier entier pendant la lecture doit arrêter l’enregistrement afin qu’une entrée incomplète ne soit pas rapportée comme un résultat complet.
Error
Une Error est un sous-type de Throwable destiné aux erreurs graves d’exécution ou d’environnement qu’une reprise ordinaire d’application ne devrait pas chercher à intercepter.
OutOfMemoryError appartient à Error ; intercepter une saisie ordinaire invalide ne résout pas un épuisement du tas.
Exception
Une exception est un objet qui décrit un événement interrompant un programme en cours d’exécution et transmet le contrôle vers un gestionnaire correspondant.
Une exception lors de l’analyse de "red" arrête l’affectation avant que le programme puisse utiliser son résultat numérique.
Exception contrôlée
Une exception contrôlée est un sous-type de Throwable situé hors des branches RuntimeException et Error, dont la gestion exige une capture ou une déclaration.
Une 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
Une exception non contrôlée appartient à RuntimeException ou Error, ou à l’une de leurs sous-classes, et n’est soumise à aucune obligation de capture ou de déclaration.
Un indice de tableau incorrect provoque une exception non contrôlée même lorsque le programme a compilé avec succès.
Exception personnalisée
Une exception personnalisée est une classe d’objets pouvant être levés, définie par l’application, qui permet aux appelants de reconnaître et de gérer une erreur précise propre au domaine.
Un système de gestion de stock utilise une exception personnalisée pour distinguer un stock insuffisant d’un argument invalide.
Exception supprimée
Une exception supprimée est une erreur supplémentaire rattachée à une exception principale, comme une erreur de fermeture après qu’un corps utilisant une ressource a déjà levé une exception.
L’exception supprimée conserve l’erreur de fermeture d’un lecteur pendant que l’erreur d’analyse d’origine se propage.

É

Échec immédiat
L’échec immédiat consiste à rejeter une entrée ou un état invalide à l’endroit où il est détecté, avant que le travail ultérieur puisse propager ou masquer le problème.
Dans un mutateur, l’échec immédiat vérifie un pourcentage invalide avant toute affectation au champ.

F

Fichier temporaire
Un fichier temporaire contient une sortie intermédiaire séparée de la destination finale, afin qu’elle puisse être terminée avant toute tentative de remplacement.
Un fichier temporaire pour un rapport est créé dans le dossier de destination avant que le texte terminé soit déplacé à son emplacement final.
Fin de ligne
Une fin de ligne est la séquence de caractères qui termine une ligne de texte, généralement LF sous Linux et macOS ou CRLF sous Windows.
Une fin de ligne lue par BufferedReader.readLine() est retirée avant que la méthode renvoie le texte de la ligne.

G

Gestionnaire inaccessible
Un gestionnaire inaccessible est une clause catch qui ne peut recevoir aucune exception car un gestionnaire précédent couvre déjà tous les types correspondants.
Placer IOException en premier crée un gestionnaire inaccessible si NoSuchFileException est interceptée ensuite.

H

Hiérarchie des exceptions
Une hiérarchie des exceptions est une structure d’héritage qui permet aux appelants d’intercepter une erreur précise ou une superclasse commune à des erreurs apparentées.
Une hiérarchie des exceptions peut placer les erreurs d’article inconnu et de stock insuffisant sous un même type de base pour le stock.

I

IllegalArgumentException
Une IllegalArgumentException est une exception non contrôlée utilisée lorsqu’un appelant fournit une valeur qui ne respecte pas les exigences d’une méthode pour ses arguments.
Une méthode peut lever IllegalArgumentException lorsque la quantité positive requise lui est fournie sous la forme -2.
IllegalStateException
Une IllegalStateException est une exception non contrôlée utilisée lorsque l’état actuel d’un objet ne permet pas l’opération demandée.
Une commande déjà envoyée peut lever IllegalStateException lorsque le code tente d’y ajouter un autre article.
InputMismatchException
Une InputMismatchException est une exception non contrôlée de scanner levée lorsqu’un jeton ne correspond pas au type ou à l’intervalle demandé par une méthode de conversion.
nextInt() lève InputMismatchException sur "several" et laisse ce jeton disponible pour être écarté.
Instruction try avec gestion des ressources
L’instruction try avec gestion des ressources est une instruction Java qui ferme automatiquement les ressources AutoCloseable ouvertes avec succès lorsque le travail protégé se termine.
L’instruction try avec gestion des ressources ferme un objet d’écriture avant le lecteur lorsque leurs déclarations dans l’en-tête ouvrent d’abord le lecteur.

L

Ligne d’en-tête
Une ligne d’en-tête nomme les colonnes d’un fichier de données et est traitée séparément afin que ses noms ne soient pas analysés comme des valeurs d’enregistrement ordinaires.
La ligne d’en-tête "name,age" doit être ignorée ou vérifiée avant que l’analyseur tente de convertir un âge.

M

Masquage d’exception
Le masquage d’exception se produit lorsqu’un transfert de contrôle ultérieur remplace une erreur antérieure et cache l’exception d’origine à l’appelant.
Un retour dans finally peut provoquer un masquage d’exception en écartant une erreur levée dans le bloc try.

N

Nettoyage
Le nettoyage est le travail qui libère des ressources ou rétablit un paramètre lorsqu’une opération se termine, y compris sur les chemins quittés à cause d’une erreur.
Le nettoyage ferme un fichier ouvert même lorsque la conversion de l’un de ses enregistrements lève une exception.
NullPointerException
Une NullPointerException est une exception non contrôlée levée lorsqu’une opération exige un objet mais reçoit ou utilise une référence nulle.
Appeler name.trim() lorsque name vaut null lève NullPointerException avant le renvoi de tout texte débarrassé des caractères blancs autour.
NumberFormatException
Une NumberFormatException est une exception non contrôlée levée lorsqu’une conversion de texte numérique ne peut pas produire la valeur numérique demandée.
Integer.parseInt("blue") lève NumberFormatException car le texte ne peut pas représenter un entier.

O

Ordre des clauses catch
L’ordre des clauses catch est l’ordre de haut en bas dans lequel les gestionnaires sont testés ; il impose qu’un gestionnaire de sous-classe précède celui de sa superclasse.
L’ordre des clauses catch place NoSuchFileException avant IOException lorsque chacune nécessite un message distinct.

P

Paramètres régionaux
Les paramètres régionaux fournissent des conventions de langue et de formatage régional qui peuvent influer sur l’analyse des nombres par un scanner et sur la sortie décimale formatée.
Choisir les paramètres régionaux racine fait utiliser "3.50" aux données décimales formatées, quels que soient les réglages de l’ordinateur.
Path
Un Path est un objet qui représente un emplacement dans un système de fichiers ; sa construction n’ouvre pas, ne crée pas et ne vérifie pas le fichier désigné.
Path.of("data", "counts.txt") construit un Path sans vérifier si le dossier de données existe.
Pile d’appels
La pile d’appels est la chaîne des appels de méthodes actuellement actifs dans un thread, chaque appel attendant la fin du travail qu’il a demandé.
Lorsque main appelle load, qui appelle parse, la pile d’appels enregistre les trois appels de méthodes actifs.
PrintWriter
Un PrintWriter écrit une sortie de caractères formatée avec des méthodes d’affichage qui enregistrent les erreurs d’entrée-sortie en interne pour que checkError les signale.
Un PrintWriter peut formater une moyenne avec printf, mais le retour normal de cet appel ne prouve pas que l’enregistrement a réussi.
Propagation
La propagation est la transmission d’une exception non gérée vers l’extérieur, à travers le code englobant et les méthodes appelantes, jusqu’à ce qu’un gestionnaire soit trouvé.
La propagation transmet une erreur de lecture hors d’une méthode auxiliaire de lecture de fichier jusqu’à un appelant qui peut demander un autre fichier.

R

Région protégée
Une région protégée est le travail encadré par une instruction try ; ses limites déterminent ce qui est abandonné lorsqu’une erreur atteint son gestionnaire.
La région protégée couvre un enregistrement lorsqu’une instruction try de conversion se trouve dans le corps de la boucle.
Règle de capture ou de déclaration
La règle de capture ou de déclaration exige que le code qui peut lever une exception contrôlée la gère ou énumère un type applicable dans sa déclaration de méthode.
La règle de capture ou de déclaration s’applique à une méthode qui appelle Files.readString, même lorsque le fichier qu’elle lit existe.
Répertoire de travail
Le répertoire de travail est le dossier courant du programme qui sert de point de départ aux chemins relatifs ; il peut différer du dossier du code source.
Avec /work/app comme répertoire de travail, data/counts.txt désigne un fichier dans /work/app/data.
Reprise après erreur
La reprise après erreur est la réponse du programme qui lui permet de continuer utilement après un échec, par exemple en réessayant ou en ignorant un enregistrement incorrect.
Dans une boucle de saisie, la reprise après erreur lit une nouvelle ligne avant d’essayer une autre conversion, afin de pouvoir progresser.
Ressource
Une ressource est un objet qui détient un élément externe, comme un fichier ouvert, et qui doit être libéré après son utilisation.
Un lecteur de fichier est une ressource qui doit être fermée même lorsque le traitement de sa ligne suivante échoue.
Retour en attente
Un retour en attente est un retour dont l’expression a été évaluée, mais dont le transfert à l’appelant attend la fin du nettoyage nécessaire.
Modifier un entier local pendant finally ne réévalue pas l’expression d’un retour en attente.
RuntimeException
RuntimeException est la sous-classe de Exception dont les descendants représentent des erreurs non contrôlées, notamment les arguments invalides et l’utilisation d’une référence nulle.
NumberFormatException atteint RuntimeException par sa superclasse IllegalArgumentException.

S

Scanner
Un Scanner lit du texte sous forme de jetons ou de lignes et propose des méthodes de conversion, tout en enregistrant les erreurs sous-jacentes de lecture d’entrée-sortie pour un examen ultérieur.
Un 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
Un tampon est une zone de mémoire qui conserve temporairement du texte avant sa transmission à un fichier, ce qui réduit le nombre de petites opérations de sortie.
Le tampon d’un objet d’écriture peut encore contenir la dernière ligne du rapport jusqu’à son vidage ou à la fermeture de l’objet.
throw
Le mot-clé throw commence une instruction qui fait sortir un objet exception de l’opération en cours et interrompt son exécution normale.
Un throw avant l’affectation à un champ rejette une capacité invalide tout en conservant l’ancienne valeur du champ.
Throwable
Throwable est la superclasse Java des objets qui peuvent être levés ; Error et Exception sont ses deux principales sous-classes directes.
Une exception contrôlée personnalisée appartient à Throwable par l’intermédiaire de Exception ; Java peut donc la lever et l’intercepter.
Trace de pile
Une trace de pile présente une exception et ses appels de méthodes actifs, en commençant par le point de détection et en poursuivant par ses appelants.
Lorsqu’une méthode auxiliaire appelée par main échoue lors d’une conversion, la trace de pile indique d’abord la conversion, puis la méthode auxiliaire et main.
Troncature
La troncature supprime le contenu d’un fichier existant lorsqu’il est ouvert pour remplacement, avant même que la nouvelle sortie ait nécessairement été écrite avec succès.
Files.writeString provoque une troncature par défaut ; une erreur d’écriture ultérieure peut donc laisser un résultat incomplet.

U

UncheckedIOException
Une UncheckedIOException est une sous-classe standard de RuntimeException qui encapsule une IOException tout en conservant l’erreur de fichier d’origine comme cause.
Une méthode redéfinie qui ne peut pas déclarer IOException peut transmettre une erreur de fichier avec UncheckedIOException.
UTF-8
UTF-8 est un encodage de caractères Unicode qui utilise un octet pour les caractères latins de base et jusqu’à quatre octets pour les autres caractères Unicode.
En UTF-8, « café » occupe cinq octets bien qu’il ne contienne que quatre caractères visibles.

V

Vidage du tampon
Le vidage du tampon transmet à sa destination la sortie en attente dans le tampon d’un objet d’écriture ; il ne libère pas lui-même la ressource ouverte.
Le vidage du tampon fait sortir le texte en attente du tampon de l’objet d’écriture, mais le programme doit encore fermer sa ressource de fichier.

À propos de cette unité

Par StudeliSignaler une erreur

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.

Commencer