CodeGym /Cours /C# SELF /Lecture de fichiers texte :

Lecture de fichiers texte : StreamReader

C# SELF
Niveau 36 , Leçon 2
Disponible

1. Intro

Imagine, on doit encore lire le contenu d’un fichier texte. Disons qu’on a un fichier avec des citations sympas de devs qu’on veut afficher dans notre appli console préférée. Ouais, on a déjà vu les méthodes haut niveau genre File.ReadAllText, mais si le fichier est énorme, et qu’on veut le lire ligne par ligne ? Ou alors on veut le lire doucement, genre charger les lignes petit à petit pour pas exploser la RAM ?

C’est là que StreamReader débarque — une classe parfaite pour lire des fichiers texte ligne par ligne, par blocs, caractère par caractère — bref, super flexible et pratique.

Comment marche StreamReader ?

StreamReader — c’est une classe du namespace System.IO, qui sert à lire des données texte depuis un stream (en général un fichier, mais ça peut aussi être un stream réseau ou la mémoire). Il sait lire les données dans l’encodage qu’il faut, les convertir en caractères et lignes, et te renvoyer des types bien pratiques : string et char.

Si on schématise, ça donne un truc comme ça :


[ Fichier (octets) ] --(FileStream)--> [ StreamReader (décode les caractères) ] ---> [ Ton code (string, char) ]
  • Fichier (ou autre source d’octets) : Donne les octets.
  • FileStream : Lit ces octets, comme un "canal".
  • StreamReader : Transforme les octets en caractères et lignes selon l’encodage (par défaut — UTF-8).

Pourquoi il ne faut pas toujours utiliser juste File.ReadAllText ?

Dans la vraie vie, les fichiers peuvent être énormes. Vraiment énormes (genre des logs ou des csv avec un million de lignes). Essayer de tout charger en mémoire d’un coup — c’est comme vouloir bouffer tout un gâteau d’un coup : c’est bon, mais tu risques de le regretter.
StreamReader lit le fichier "par morceaux". Il ne charge pas tout en RAM, il lit et te file la prochaine ligne ou caractère seulement quand tu le demandes. C’est économe et super pratique.

2. Lire un fichier entier ligne par ligne

On va créer un fichier quotes.txt avec ces lignes :


Le code, c’est de la poésie.
Le debug, c’est du détective.
"Ça marche pas" — meilleur bug report.

Maintenant, on ajoute du code à notre appli d’apprentissage (genre une appli console simple qu’on fait évoluer petit à petit). On met le fichier à côté du .exe — comme ça le programme le lit et affiche le contenu ligne par ligne.

Code commenté :


// On récupère le chemin du fichier dans le dossier du programme
string fileName = "quotes.txt";
string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);

// On vérifie si le fichier existe
if (!File.Exists(filePath))
{
    Console.WriteLine($"Fichier introuvable : {filePath}");
    return;
}

// On ouvre le fichier en lecture avec StreamReader
using StreamReader reader = new StreamReader(filePath);
string? line;
int lineNumber = 1;

// On lit le fichier ligne par ligne jusqu’à la fin
while ((line = reader.ReadLine()) != null)
{
    Console.WriteLine($"{lineNumber,2}: {line}");
    lineNumber++;
}

Qu’est-ce qui se passe ici ?

  • On calcule le chemin du fichier avec Path.Combine et AppDomain.CurrentDomain.BaseDirectory — comme ça le code marche pareil sur Windows, Linux et même dans un conteneur Docker.
  • D’abord on vérifie que le fichier existe vraiment.
  • Avec using on crée un StreamReader et on lit le fichier ligne par ligne (méthode ReadLine()).
  • À la fin du bloc using le fichier est fermé, même si t’as oublié de le faire à la main ou si une exception est levée.

Visualisation : schéma du process


[ quotes.txt ] --(FileStream)--> [ StreamReader ] --(ReadLine)--> [ string line ] --(Console.WriteLine)--> Écran
    ^                                                       
    |
AppDomain.CurrentDomain.BaseDirectory + Path.Combine

3. Particularités et subtilités d’utilisation

Comment la lecture des lignes fonctionne

La méthode ReadLine() renvoie la ligne jusqu’au premier caractère de nouvelle ligne (\n ou \r\n). Quand le fichier est fini, ça renvoie null. Donc la boucle ressemble souvent à ça :


string? line;
while ((line = reader.ReadLine()) != null)
{
    // traitement de la ligne
}

Erreurs classiques avec StreamReader

Parfois, on a envie de ne pas utiliser using, et d’écrire juste :


StreamReader reader = new StreamReader(filePath);
// ...
reader.Close();

Ce genre de code — c’est comme oublier de fermer la porte quand il fait froid : tout peut arriver. Si une erreur arrive pendant la lecture (genre le disque devient inaccessible), le code pour fermer le fichier ne sera pas exécuté, et le fichier reste ouvert dans le système.
Donc utiliser using — c’est pas juste un conseil, c’est vraiment obligatoire. Ton futur collègue admin système te remerciera parce que ton programme ne laisse pas des fichiers "zombies" ouverts partout.

Syntaxe courte avec using declaration

Avec les versions récentes de C# (depuis la 8.0), tu peux écrire plus court :


using StreamReader reader = new StreamReader(filePath);
string? line;
while ((line = reader.ReadLine()) != null)
{
    Console.WriteLine(line);
}

Dispose sera appelé à la fin du bloc courant (méthode).

4. Astuces utiles

Lire un fichier avec un encodage inconnu

Par défaut, StreamReader bosse en UTF-8. Mais parfois, tu tombes sur des fichiers avec un autre encodage (genre Windows-1251 pour de vieux textes russes). Dans ce cas, le programme peut afficher des "?" ou des caractères illisibles.

Tu peux préciser l’encodage :


using System.Text;

// On ouvre le fichier en Windows-1251
using StreamReader reader = new StreamReader(filePath, Encoding.GetEncoding("windows-1251"));

Doc sur les encodages et Encoding

Lire tout le fichier comme un seul gros texte

Parfois, tu veux tout le fichier d’un coup, mais pas avec File.ReadAllText, mais via StreamReader.


using StreamReader reader = new StreamReader(filePath);
string allText = reader.ReadToEnd();
Console.WriteLine(allText);
  • La méthode ReadToEnd() lit tout le contenu du fichier depuis la position actuelle jusqu’à la fin comme une seule string.
  • Pour les gros fichiers, ça peut être inefficace et tu risques un OutOfMemoryException. Pour des fichiers de quelques Mo, ça passe.

À quoi ça sert dans la vraie vie

  • Analyse de logs. Si t’as un fichier de logs serveur, c’est pratique de le lire ligne par ligne, filtrer les events utiles et ne pas tout charger en RAM.
  • Import CSV. Si tu dois parser de gros tableaux, c’est cool de lire les données ligne par ligne et de les traiter au fur et à mesure.
  • Recherche de mots-clés dans de gros fichiers texte. Tu peux chercher du texte dans des millions de lignes sans te soucier de la mémoire.
  • Tests unitaires. Les fichiers de données de test sont souvent lus ligne par ligne avec StreamReader.

Comparaison des méthodes de lecture

Méthode Quand l’utiliser Avantages Inconvénients
File.ReadAllText
Petits fichiers Une ligne de code, rapide Gros fichier = beaucoup de mémoire
StreamReader.ReadLine()
Tous, surtout les gros fichiers Lecture ligne par ligne, peu de mémoire Un peu plus de code, logique un peu plus complexe
StreamReader.ReadToEnd()
Petits/moyens fichiers Gestion flexible de l’encodage Galère avec les très gros fichiers

5. Pratique

On va corser un peu. Que notre programme affiche seulement les N premières lignes du fichier, où N est donné par l’utilisateur. Avoue, parfois t’as pas envie de voir des centaines de lignes — deux-trois citations suffisent pour la motiv’ :)

Voilà comment faire :


using System;
using System.IO;

class Program
{
    static void Main()
    {
        string fileName = "quotes.txt";
        string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);

        if (!File.Exists(filePath))
        {
            Console.WriteLine($"Fichier introuvable : {filePath}");
            return;
        }

        Console.Write("Combien de lignes afficher ? ");
        string? input = Console.ReadLine();
        if (!int.TryParse(input, out int linesToShow) || linesToShow < 1)
        {
            Console.WriteLine("Erreur : Entre un nombre correct supérieur à 0.");
            return;
        }

        using StreamReader reader = new StreamReader(filePath);

        int current = 0;
        string? line;
        while (current < linesToShow && (line = reader.ReadLine()) != null)
        {
            Console.WriteLine(line);
            current++;
        }

        if (current == 0)
            Console.WriteLine("Fichier vide ou impossible de lire la première ligne.");
        else if (current < linesToShow)
            Console.WriteLine($"Le fichier avait seulement {current} ligne(s).");
    }
}

6. Points importants et pièges classiques

Quand tu bosses avec StreamReader, le plus important — c’est de bien gérer les ressources (cf. la conf précédente sur IDisposable). Si tu oublies, tu peux avoir l’erreur "fichier déjà utilisé par un autre process" ou "trop de fichiers ouverts".

Autre subtilité — fais gaffe à l’encodage. Si t’es pas sûr que le fichier est en UTF-8, précise l’encodage voulu. Pour ça, y’a un deuxième paramètre dans le constructeur de StreamReader.

Encore un piège pratique : si le fichier est modifié pendant que le programme tourne (genre un fichier de log), tu ne verras pas toujours les nouvelles lignes tout de suite si le fichier est utilisé par d’autres process — dans ce cas, il faut relire ou recalculer le fichier, ou utiliser des méthodes spéciales, mais on en parlera plus tard.

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