CodeGym /Cours /JAVA 25 SELF /Traitement des fichiers endommagés, récupération des donn...

Traitement des fichiers endommagés, récupération des données

JAVA 25 SELF
Niveau 38 , Leçon 2
Disponible

1. Signes d’un fichier endommagé

Dans un monde idéal, les fichiers se lisent et s’écrivent toujours sans erreur, et les données qu’ils contiennent sont comme des petits pains tout juste sortis du four : moelleux, parfumés, réguliers, intacts. Mais en réalité, les fichiers peuvent être « corrompus », « bancals », « incomplets » ou « d’un format inattendu ». Les causes peuvent être variées. Par exemple, une panne pendant l’écriture sur le disque (coupure de courant soudaine), des erreurs réseau lors du transfert, une défaillance du support (le bon vieux bad sector). De même, une modification manuelle dans un logiciel inadéquat peut endommager le fichier, tout comme un écart entre le format attendu et le format effectif des données.

En Java, ces situations se manifestent généralement par des exceptions lors de la lecture/écriture, et parfois par un comportement étrange du programme (par exemple, les données se terminent soudainement ou du charabia apparaît).

Exceptions à la lecture

Le signe le plus évident — des exceptions inattendues. En voici quelques-unes :

  • EOFException — fin de fichier inattendue (End Of File). Vous vous attendiez à ce qu’il reste des données dans le fichier, mais il n’y en a pas.
  • MalformedInputException (ou, dans les anciennes API, MalformedInputException de NIO) — le fichier ne correspond pas à l’encodage ou à la structure attendus.
  • ZipException — par exemple si vous tentez de lire une archive comme un fichier ordinaire.
  • StreamCorruptedException — lors de la lecture d’objets sérialisés si le fichier est endommagé.

Non-conformité du format des données

Parfois, le fichier se lit sans exception, mais son contenu ne correspond pas au format attendu :

  • Vous attendiez une chaîne, et vous obtenez un ensemble de symboles incompréhensibles.
  • Vous attendiez un certain nombre de valeurs numériques, et il y en a moins.
  • Vous attendiez un fichier au format CSV, et c’est du JSON (ou l’inverse).

Exemple concret

Supposons que vous écriviez une application qui stocke une liste de tâches dans un fichier texte. Le programme s’attend à ce que chaque ligne soit une tâche séparée. Mais l’utilisateur a décidé d’ouvrir le fichier dans Excel, a apporté des modifications, l’a enregistré dans un autre format… et votre programme ne peut plus lire le fichier.

2. Stratégies de gestion des fichiers endommagés

Journalisation et information de l’utilisateur

Première règle : ne pas paniquer ! (et ne pas faire paniquer l’utilisateur). Consignez toujours l’erreur dans les logs et informez l’utilisateur si quelque chose s’est mal passé. En revanche, il n’est pas nécessaire de lui exposer toutes les horreurs de la pile Java.

try {
    // lecture du fichier
} catch (EOFException e) {
    System.err.println("Le fichier s'est terminé de manière inattendue. Il est peut-être endommagé.");
    // on journalise les détails
    e.printStackTrace();
}

Tentative de récupération partielle

Parfois, on peut « sauver » au moins une partie des données. Par exemple, si le fichier est lu ligne par ligne, il est possible de traiter toutes les lignes jusqu’à la première erreur.

Utilisation de sauvegardes (backup)

Les applications sérieuses créent souvent des copies de sauvegarde des fichiers importants avant l’écriture. Si le fichier principal est endommagé, on peut tenter de restaurer les données depuis la sauvegarde.

3. Pratique : lecture d’un fichier avec fin inattendue (EOF)

Cas classique

Supposons que nous ayons un fichier binaire dans lequel des entiers (int) sont écrits séquentiellement. Le programme s’attend à en lire exactement 5, mais le fichier a été endommagé et seulement 3 ont été écrits.

import java.io.*;

public class DamagedFileExample {
    public static void main(String[] args) {
        String filename = "numbers.bin";

        // Pour l'exemple : créer un fichier avec 3 nombres (au lieu de 5)
        try (DataOutputStream out = new DataOutputStream(new FileOutputStream(filename))) {
            out.writeInt(42);
            out.writeInt(7);
            out.writeInt(2024);
            // out.writeInt(1); out.writeInt(2); // nous ne les écrivons pas volontairement !
        } catch (IOException e) {
            System.err.println("Erreur lors de la création du fichier : " + e.getMessage());
        }

        // Maintenant, essayons de lire 5 nombres
        try (DataInputStream in = new DataInputStream(new FileInputStream(filename))) {
            for (int i = 0; i < 5; i++) {
                int number = in.readInt();
                System.out.println("Nombre lu : " + number);
            }
        } catch (EOFException e) {
            System.err.println("Le fichier s'est terminé de manière inattendue ! Il est peut-être endommagé.");
        } catch (IOException e) {
            System.err.println("Erreur de lecture : " + e.getMessage());
        }
    }
}

Résultat :

Nombre lu : 42
Nombre lu : 7
Nombre lu : 2024
Le fichier s'est terminé de manière inattendue ! Il est peut-être endommagé.

Lire jusqu’à la première erreur

Il est souvent judicieux de lire les données dans une boucle jusqu’à ce qu’une exception survienne. On obtient ainsi au moins une partie des informations.

try (DataInputStream in = new DataInputStream(new FileInputStream(filename))) {
    while (true) {
        try {
            int number = in.readInt();
            System.out.println("Nombre lu : " + number);
        } catch (EOFException e) {
            System.out.println("Les données sont terminées (ou le fichier est endommagé).");
            break;
        }
    }
} catch (IOException e) {
    System.err.println("Erreur de lecture : " + e.getMessage());
}

4. Travail avec des fichiers texte et les encodages

Problème d’encodage

Si un fichier a été enregistré dans un encodage et lu dans un autre, des erreurs de décodage peuvent se produire :

import java.nio.charset.*;

try (BufferedReader reader = new BufferedReader(
        new InputStreamReader(new FileInputStream("tasks.txt"), "UTF-8"))) {
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
} catch (MalformedInputException e) {
    System.err.println("Erreur d'encodage ! Le fichier est endommagé ou n'a pas été enregistré en UTF-8.");
} catch (IOException e) {
    System.err.println("Erreur de lecture : " + e.getMessage());
}

Important : Parfois, au lieu d’une exception, vous obtiendrez des « caractères illisibles » — c’est également un signe d’endommagement ou d’un encodage incorrect.

Comment traiter ?

  • Informer l’utilisateur du problème.
  • Essayer d’ouvrir le fichier avec un autre encodage.
  • Si les données sont critiques, proposer de restaurer depuis une sauvegarde.

5. Récupération des données : stratégies

Lecture de données partiellement correctes

Si la structure du fichier le permet, on peut « extraire » au moins les données lues avant l’erreur. Par exemple, si le fichier est une liste de lignes (une tâche par ligne), on peut traiter toutes les lignes jusqu’à la panne.

try (BufferedReader reader = new BufferedReader(new FileReader("tasks.txt"))) {
    String line;
    while ((line = reader.readLine()) != null) {
        // traitement de la ligne
    }
} catch (IOException e) {
    System.err.println("Erreur de lecture : " + e.getMessage());
    // Vous pouvez enregistrer les données déjà lues ou proposer une restauration à l'utilisateur
}

Utilisation de fichiers de sauvegarde (backup)

Si vous créez à l’avance une copie du fichier (par exemple, tasks.txt.bak

File original = new File("tasks.txt");
File backup = new File("tasks.txt.bak");

if (!original.exists() && backup.exists()) {
    // Copier le backup à la place de l'original
    Files.copy(backup.toPath(), original.toPath(), StandardCopyOption.REPLACE_EXISTING);
    System.out.println("Restauration depuis la sauvegarde terminée.");
}

Sommes de contrôle et validation

Pour les fichiers importants, on peut conserver une somme de contrôle (par exemple, MD5 ou SHA-256) et, à chaque ouverture, la comparer à la valeur actuelle. Si elles ne correspondent pas — le fichier est endommagé.

// Schéma approximatif (l'implémentation du hachage est omise pour simplifier)
String expectedHash = "..."; // somme enregistrée précédemment
String actualHash = calculateFileHash("tasks.txt");
if (!expectedHash.equals(actualHash)) {
    System.out.println("Le fichier tasks.txt est endommagé ! Essayez de restaurer depuis une sauvegarde.");
}

6. Erreurs typiques lors du traitement de fichiers endommagés

Erreur n° 1 : Le format du fichier n’est pas vérifié. Si vous attendez que chaque ligne soit, par exemple, un nombre, mais qu’il s’agit de texte, une NumberFormatException se produira. Il vaut mieux valider les données au fur et à mesure de la lecture.

Erreur n° 2 : Absence de try-with-resources. Si vous n’utilisez pas try-with-resources, le fichier peut rester « en suspens » (non fermé) même en cas d’erreur, ce qui compliquera la restauration ou la suppression.

Erreur n° 3 : Réécriture d’un fichier endommagé sans créer de sauvegarde. Si, en cas d’erreur, vous réécrivez immédiatement le fichier, les chances de récupération diminuent. Il vaut mieux enregistrer d’abord un backup.

Erreur n° 4 : Restauration peu informative. L’utilisateur doit savoir que le fichier a été endommagé et restauré à partir d’une copie — sinon il risque de ne pas comprendre pourquoi une partie des données a disparu.

Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION