CodeGym /Cours /JAVA 25 SELF /Lecture et écriture de fichiers : opérations de base

Lecture et écriture de fichiers : opérations de base

JAVA 25 SELF
Niveau 35 , Leçon 2
Disponible

1. Lecture d’un fichier en entier

Lecture de tous les octets

Parfois, il faut extraire tout le contenu d’un fichier d’un seul coup — tel quel, sans interprétation, que ce soit une image, une archive ou un format binaire quelconque. Pour cela, Java propose la méthode Files.readAllBytes(path). Elle renvoie un tableau d’octets (byte[]), c’est‑à‑dire les données brutes du fichier que vous pouvez ensuite utiliser comme bon vous semble.

import java.nio.file.*;

public class ReadBytesExample {
    public static void main(String[] args) throws Exception {
        Path path = Paths.get("example.txt");
        byte[] allBytes = Files.readAllBytes(path);
        System.out.println("Longueur du fichier en octets : " + allBytes.length);
    }
}

Remarque: Si le fichier est volumineux (des gigaoctets), cette approche peut entraîner des problèmes de mémoire — car tout le contenu du fichier est chargé d’un coup en RAM.

Lecture de toutes les lignes

Pour les fichiers texte, il existe une approche plus conviviale : Files.readAllLines(path). Elle renvoie une liste de lignes (List<String>) où chaque élément correspond à une ligne du fichier (les séparateurs de ligne sont pris en charge automatiquement).

import java.nio.file.*;
import java.util.List;

public class ReadLinesExample {
    public static void main(String[] args) throws Exception {
        Path path = Paths.get("example.txt");
        List<String> lines = Files.readAllLines(path);

        for (String line : lines) {
            System.out.println(line);
        }
    }
}

Important: Par défaut, le jeu de caractères du système est utilisé. Si vous souhaitez indiquer explicitement l’encodage (par exemple, UTF-8), utilisez la version surchargée du mécanisme :

List<String> lines = Files.readAllLines(path, java.nio.charset.StandardCharsets.UTF_8);

Exemple : lecture d’un fichier et affichage à l’écran

Ajoutons ceci à notre mini‑application (par exemple, « bloc‑notes » ou « liste de tâches ») :

import java.nio.file.*;
import java.util.List;

public class TodoReader {
    public static void main(String[] args) throws Exception {
        Path todoPath = Paths.get("todo.txt");
        if (Files.exists(todoPath)) {
            List<String> tasks = Files.readAllLines(todoPath);
            System.out.println("Vos tâches pour aujourd’hui :");
            for (String task : tasks) {
                System.out.println("- " + task);
            }
        } else {
            System.out.println("Le fichier todo.txt est introuvable. Créez une liste de tâches !");
        }
    }
}

2. Écriture dans un fichier

Écriture d’un tableau d’octets

Si vous disposez d’un tableau d’octets (par exemple, le résultat d’une sérialisation, d’une image ou d’un audio), utilisez Files.write(path, bytes). Cette méthode crée le fichier s’il n’existe pas, ou écrase l’existant.

import java.nio.file.*;

public class WriteBytesExample {
    public static void main(String[] args) throws Exception {
        Path path = Paths.get("output.bin");
        byte[] data = {1, 2, 3, 4, 5};
        Files.write(path, data);
        System.out.println("Les octets ont été écrits dans le fichier output.bin");
    }
}

Écriture d’une liste de lignes

Pour les fichiers texte, il est plus pratique d’utiliser une liste de chaînes — chaque élément sera écrit sur sa propre ligne, avec un saut de ligne.

import java.nio.file.*;
import java.util.Arrays;
import java.util.List;

public class WriteLinesExample {
    public static void main(String[] args) throws Exception {
        Path path = Paths.get("todo.txt");
        List<String> tasks = Arrays.asList(
            "Acheter du lait",
            "Appeler grand-mère",
            "Faire les devoirs de Java"
        );
        Files.write(path, tasks);
        System.out.println("La liste de tâches a été écrite dans todo.txt");
    }
}

Attention: Par défaut, le fichier sera écrasé ! S’il existait déjà, les anciennes tâches disparaîtront. (Comment ne pas perdre l’ancien contenu — nous l’expliquerons un peu plus tard.)

Écriture d’une chaîne dans un fichier

Si vous souhaitez écrire une seule ligne — créez simplement une liste contenant une seule chaîne ou utilisez Files.write(path, string.getBytes()) :

import java.nio.file.*;

public class WriteStringExample {
    public static void main(String[] args) throws Exception {
        Path path = Paths.get("hello.txt");
        String message = "Bonjour, Java ! ";
        Files.write(path, message.getBytes());
        System.out.println("La chaîne a été écrite dans hello.txt");
    }
}

Indiquer explicitement l’encodage

Pour éviter les caractères illisibles lors de la manipulation de texte en russe (et pas seulement), indiquez toujours l’encodage :

import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.List;

public class WriteLinesUtf8Example {
    public static void main(String[] args) throws Exception {
        Path path = Paths.get("hello.txt");
        List<String> lines = List.of("Bonjour, le monde !", "C’est Java.");
        Files.write(path, lines, StandardCharsets.UTF_8);
    }
}

3. Gestion des erreurs

Lors de la manipulation de fichiers, Java peut lever l’exception IOException. Il s’agit d’un signal général indiquant que « quelque chose s’est mal passé » au niveau entrée/sortie. Les causes potentielles sont nombreuses : fichier absent, droits insuffisants, disque plein ou occupé, voire une clé USB débranchée au plus mauvais moment.

C’est pourquoi les méthodes de lecture et d’écriture de fichiers exigent que nous soyons prêts à gérer ces situations. On le fait au moyen de try-catch :

import java.nio.file.*;
import java.util.List;
import java.io.IOException;

public class SafeReadExample {
    public static void main(String[] args) {
        Path path = Paths.get("todo.txt");
        try {
            List<String> lines = Files.readAllLines(path);
            System.out.println("Contenu du fichier :");
            for (String line : lines) {
                System.out.println(line);
            }
        } catch (IOException ex) {
            System.out.println("Erreur lors de la lecture du fichier : " + ex.getMessage());
        }
    }
}

Pourquoi tout cela ?

try-catch transforme un plantage potentiel en situation maîtrisée. Si le fichier est absent — nous en informons calmement l’utilisateur. Si le système refuse l’accès — nous indiquons le problème. Et si le disque disparaît en plein milieu de l’opération, le programme ne s’effondrera pas avec un affreux stack trace, il affichera au moins un message compréhensible. Autrement dit : IOException n’est pas un ennemi, c’est simplement la façon dont Java nous dit : « hé, quelque chose s’est mal passé à l’extérieur, décide quoi faire ensuite ».

4. Exemples pratiques

Lire un fichier et afficher le contenu

import java.nio.file.*;
import java.util.List;
import java.io.IOException;

public class PrintFileExample {
    public static void main(String[] args) {
        Path path = Paths.get("notes.txt");
        try {
            if (!Files.exists(path)) {
                System.out.println("Le fichier notes.txt est introuvable.");
                return;
            }
            List<String> lines = Files.readAllLines(path, java.nio.charset.StandardCharsets.UTF_8);
            System.out.println("Contenu du fichier notes.txt :");
            for (String line : lines) {
                System.out.println(line);
            }
        } catch (IOException e) {
            System.out.println("Erreur lors de la lecture du fichier : " + e.getMessage());
        }
    }
}

Écrire une chaîne dans un nouveau fichier

import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.io.IOException;

public class WriteFileExample {
    public static void main(String[] args) {
        Path path = Paths.get("greeting.txt");
        String content = "Bienvenue dans le monde de Java IO !";
        try {
            Files.write(path, content.getBytes(StandardCharsets.UTF_8));
            System.out.println("La chaîne a été écrite dans le fichier greeting.txt");
        } catch (IOException e) {
            System.out.println("Erreur lors de l’écriture du fichier : " + e.getMessage());
        }
    }
}

Écrire une liste de lignes dans un fichier

import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.io.IOException;

public class WriteListExample {
    public static void main(String[] args) {
        Path path = Paths.get("shopping.txt");
        List<String> items = List.of("Pain", "Lait", "Fromage");
        try {
            Files.write(path, items, StandardCharsets.UTF_8);
            System.out.println("La liste de courses a été écrite dans shopping.txt");
        } catch (IOException e) {
            System.out.println("Erreur lors de l’écriture du fichier : " + e.getMessage());
        }
    }
}

5. Bref aperçu des flux

Les méthodes Files.readAllBytes, Files.readAllLines, Files.write relèvent du « tout ou rien » : soit tout le fichier en mémoire, soit tout le contenu écrit d’un coup sur le disque. Pour les petits fichiers, c’est pratique ; pour les gros, beaucoup moins (on peut obtenir un OutOfMemoryError ou simplement « se figer » en lisant des journaux de plusieurs gigaoctets).

Pour travailler avec de gros fichiers ou lire ligne par ligne, on utilise des flux :

  • Pour le texte : BufferedReader, BufferedWriter
  • Pour les octets : InputStream, OutputStream

Nous parlerons plus en détail des flux dans les prochains cours, mais voici un petit aperçu :

import java.nio.file.*;
import java.io.*;

public class BufferedReaderExample {
    public static void main(String[] args) {
        Path path = Paths.get("bigfile.txt");
        try (BufferedReader reader = Files.newBufferedReader(path)) {
            String line;
            while ((line = reader.readLine()) != null) {
                // Traitement de la ligne
                System.out.println(line);
            }
        } catch (IOException e) {
            System.out.println("Erreur lors de la lecture du fichier : " + e.getMessage());
        }
    }
}

6. Points utiles

  • Écrasement du fichier: Toutes les méthodes Files.write écrasent le fichier par défaut. Si vous devez ajouter à la fin, utilisez des options supplémentaires (nous en parlerons dans le prochain cours).
  • Encodage: Indiquez toujours explicitement l’encodage lorsque vous travaillez avec du texte non ASCII. Cela évite les caractères illisibles en sortie. Un bon choix est StandardCharsets.UTF_8.
  • Chemins: Utilisez Paths.get(...) pour la portabilité multiplateforme. Ne codez jamais en dur les slashs (/ ou \) manuellement.
  • Noms de fichiers: N’utilisez pas de caractères interdits (?, *, :, <, >, |, etc.), en particulier si votre code doit fonctionner sous Windows.

7. Erreurs courantes lors de la lecture et de l’écriture de fichiers

Erreur n° 1: IOException n’est pas gérée. Très souvent, les débutants écrivent Files.readAllLines(path) sans try-catch, et au premier problème (fichier introuvable, droits insuffisants, disque endommagé) le programme s’effondre. Gérez toujours les exceptions !

Erreur n° 2: Traiter de gros fichiers avec readAllBytes/readAllLines. Si le fichier pèse des centaines de mégaoctets ou des gigaoctets, tenter de le charger en entier peut « tuer » votre programme. Dans ces cas, utilisez des flux (BufferedReader).

Erreur n° 3: Encodage non spécifié lors de l’écriture/lecture de texte. Si vous n’indiquez pas l’encodage, le résultat peut varier selon les ordinateurs et les OS. Le problème se manifeste particulièrement avec le cyrillique. Utilisez StandardCharsets.UTF_8 ou l’encodage requis explicitement.

Erreur n° 4: Penser que File/Path est le fichier lui‑même. La classe File ou Path n’est qu’un « raccourci » vers le fichier, pas le fichier lui‑même. Créer l’objet ne crée pas le fichier sur le disque. Pour créer un fichier — utilisez les méthodes Files.createFile, Files.write, etc.

Erreur n° 5: Oublier de fermer le flux (si vous utilisez des flux). Si vous utilisez les flux manuellement (par exemple, BufferedReader), fermez‑les absolument (de préférence via try-with-resources). Sinon, le fichier peut rester « verrouillé » et indisponible pour d’autres programmes.

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