CodeGym /Cours /C# SELF /Travailler avec les fichiers en C# : la classe

Travailler avec les fichiers en C# : la classe System.IO.File

C# SELF
Niveau 35 , Leçon 2
Disponible

1. La classe File : simplicité et efficacité

La classe System.IO.File incarne le concept "une opération — une méthode". Elle propose un ensemble de méthodes haut niveau qui encapsulent toute la logique compliquée d’interaction avec l’OS, te permettant de te concentrer sur ta tâche.

Qu’est-ce que la classe File sait faire concrètement ?

  • Écrire du texte ou des données binaires quelconques dans un fichier.
  • Lire le contenu d’un fichier en entier ou ligne par ligne (pour les fichiers texte).
  • Copier, supprimer et renommer des fichiers existants.
  • Vérifier l’existence d’un fichier à un chemin donné.
  • Travailler avec les attributs du fichier (par exemple, date de création, taille – via des classes associées).

Pourquoi c’est pratique ?
Toutes les méthodes de File sont statiques. Ça veut dire que t’as pas besoin de créer un objet pour les utiliser, tu appelles juste la méthode qu’il te faut, genre :

File.WriteAllText("data.txt", "Salut, fichier !");

Ce style ressemble beaucoup à l’utilisation de la classe Console : tout est simple et clair, pas besoin de "créer" quoi que ce soit, pas besoin de se soucier des flux.

Si tu veux un outil universel et pratique pour manipuler des fichiers, la classe System.IO.File est exactement ça. Elle propose plein de méthodes pour lire, écrire, copier, supprimer et faire d’autres opérations de base sur les fichiers, un vrai couteau suisse pour le système de fichiers.

Comment utiliser File ?

Toutes les méthodes de la classe File sont statiques, donc pas besoin de créer un objet pour les utiliser — tu écris juste File.Truc(). C’est vraiment comme les appels du genre Console.WriteLine(), mais pour les fichiers.

string text = "Salut, monde !";
string path = "hello.txt";

// Écrire du texte dans un fichier (si le fichier existe, il sera écrasé !)
File.WriteAllText(path, text);

// Lire tout le fichier dans une seule string
string readText = File.ReadAllText(path);

Console.WriteLine("Contenu du fichier : " + readText);

Astuce : Si tu écris ReadAllText et WriteAllText dix fois de suite, c’est sûrement que tu fais un truc pas optimal — ces méthodes sont top pour les scénarios simples et les petits fichiers.

Méthodes les plus utilisées de la classe File

Méthode Description
File.Exists(path)
Vérifie si le fichier existe à l’emplacement indiqué
File.Delete(path)
Supprime le fichier
File.Copy(src, dest)
Copie le fichier
File.Move(src, dest)
Déplace (ou renomme) le fichier
File.ReadAllText(path)
Lit tout le fichier comme une seule string
File.WriteAllText(path, t)
Écrit une string dans le fichier (écrase si déjà existant)
File.ReadAllLines(path)
Lit toutes les lignes du fichier dans un tableau de strings
File.WriteAllLines(path, a)
Écrit un tableau de strings dans le fichier (chaque string = une ligne)
File.ReadAllBytes(path)
Lit tous les octets du fichier dans un tableau de bytes
File.WriteAllBytes(path, b)
Écrit un tableau de bytes dans le fichier

2. Écriture et lecture de fichiers texte

Voyons les méthodes les plus utilisées de la classe File avec des exemples concrets. Pour les utiliser, il faut toujours la directive using System.IO; au début de ton fichier code.

using System;
using System.IO; // Obligatoire pour bosser avec la classe File
using System.Linq; // Peut servir pour ReadLines

Lire un fichier en entier

C’est une des tâches les plus courantes : sauvegarder des données texte dans un fichier ou les recharger.

Écrire une ligne (ou tout le texte) dans un fichier : File.WriteAllText() Cette méthode crée un nouveau fichier à l’emplacement indiqué. Si un fichier du même nom existe déjà, son contenu sera complètement écrasé par le nouveau texte.

string myFilePath = "notes.txt";
string textContent = "Aujourd’hui est une super journée pour apprendre C#.\nN’oublie pas de faire tes devoirs.";

// On écrit tout le texte dans le fichier
File.WriteAllText(myFilePath, textContent); 
Console.WriteLine($"Le fichier '{myFilePath}' a été créé/écrasé avec succès.");

Lire tout le fichier dans une seule string : File.ReadAllText() Cette méthode lit tout le contenu du fichier texte du début à la fin et le renvoie sous forme d’une grosse string.

string myFilePath = "notes.txt";

// Important : vérifie toujours que le fichier existe avant de lire, pour éviter les erreurs !
if (File.Exists(myFilePath))
{
    string content = File.ReadAllText(myFilePath);
    Console.WriteLine($"Contenu du fichier '{myFilePath}' :\n{content}");
}
else
{
    Console.WriteLine($"Erreur : Le fichier '{myFilePath}' n’a pas été trouvé pour la lecture.");
}

Remarque importante : Les méthodes File.WriteAllText() et File.ReadAllText() sont parfaites pour les petits et moyens fichiers (genre notes, fichiers de config, petits logs). Mais si le fichier est très gros (genre des dizaines ou centaines de méga, voire des gigas), charger tout le contenu d’un coup en mémoire peut bouffer énormément de RAM et même causer une OutOfMemoryException. Pour ces cas, il y a des méthodes plus efficaces (on en parle plus bas et dans les prochaines confs).

3. Lecture ligne par ligne

Quand tu bosses avec de gros fichiers texte, genre des CSV énormes, des logs longs ou des bases texte, lire tout d’un coup en mémoire (c’est-à-dire charger tout le fichier du disque dans la RAM) devient inefficace ou même impossible. C’est là que File.ReadLines() sauve la vie.

File.ReadLines(path) — cette méthode ne charge pas tout le fichier d’un coup. À la place, elle renvoie une collection spéciale (IEnumerable<string>) qui te permet de lire le fichier ligne par ligne à la demande. On appelle ça "lecture paresseuse" ou "lecture en streaming".

string logFilePath = "application.log";
string text = """
INFO: Application lancée.
WARN: Problème détecté dans le module X.
ERROR: Erreur critique réseau.
INFO: Application arrêtée.    
""";    
    
// Imaginons qu’on a un fichier log avec plein de lignes.
File.WriteAllText(logFilePath, text);

// Chaque itération du foreach lit et traite UNE seule ligne à la fois 
foreach (string line in File.ReadLines(logFilePath))
    Console.WriteLine($"- {line}");

Avantage : Le fichier est lu et traité par morceaux, ce qui réduit vachement la conso mémoire quand tu bosses avec de gros fichiers.

Différence entre File.ReadLines() et File.ReadAllLines() :

  • File.ReadAllLines(path) : Charge toutes les lignes du fichier d’un coup en mémoire et les renvoie sous forme de tableau string[]. Après l’appel, tout le fichier est déjà en RAM. Pratique si tu veux accéder à toutes les lignes en même temps (genre pour trier ou chercher).
  • File.ReadLines(path) : Renvoie un IEnumerable<string> qui te permet de parcourir les lignes une par une. Le fichier est lu seulement quand tu demandes la ligne suivante (genre dans un foreach). C’est plus efficace pour les très gros fichiers, quand tu ne veux pas tout charger en mémoire.

4. Écrire un tableau de lignes

Parfois, t’as une liste de strings (genre d’une collection) et tu veux écrire chaque string comme une ligne séparée dans un fichier.

File.WriteAllLines(path, contents)

Cette méthode prend un tableau de strings (ou n’importe quelle collection de strings) et écrit chaque string comme une ligne séparée dans le fichier. Comme WriteAllText(), elle écrase le fichier s’il existe déjà.

string membersFilePath = "participants.txt";
string[] names = { "Ivan Petrov", "Maria Sidorova", "Sergey Kozlov", "Anna Kouznetsova" };

// Chaque string du tableau sera écrite comme une ligne dans le fichier
File.WriteAllLines(membersFilePath, names);

// On vérifie le contenu
Console.WriteLine($"Contenu de '{membersFilePath}' :");
foreach (string line in File.ReadLines(membersFilePath))
    Console.WriteLine($"- {line}");

5. Travailler avec les fichiers binaires

La classe File ne se limite pas aux données texte. Elle propose aussi des méthodes pratiques pour lire et écrire des données binaires, c’est-à-dire des octets bruts. C’est utile, par exemple, pour sauvegarder des configs dans un format spécial, bosser avec des images, de l’audio ou n’importe quelles données non texte.

Écrire un tableau de bytes : File.WriteAllBytes() Crée ou écrase un fichier en y écrivant tout le tableau de bytes fourni.

string binaryDataPath = "settings.bin";
// Exemple de données binaires : image, vidéo, n’importe quoi
byte[] settingsData = { 0x01, 0x0A, 0x2C, 0xFF, 0x00, 0x3F }; // Quelques "brutes" configs

File.WriteAllBytes(binaryDataPath, settingsData);
Console.WriteLine($"Données binaires écrites dans le fichier '{binaryDataPath}'.");

Important : si tu ouvres 'settings.bin' dans le Bloc-notes, tu verras des caractères illisibles ("des trucs bizarres"), parce que ces bytes ne sont pas faits pour être lus comme du texte.

Lire un tableau de bytes : File.ReadAllBytes() Lit tout le contenu d’un fichier binaire dans un tableau de bytes.

if (File.Exists(binaryDataPath))
{
    byte[] readSettings = File.ReadAllBytes(binaryDataPath);
    Console.WriteLine($"Lu {readSettings.Length} octets depuis le fichier '{binaryDataPath}'.");

    Console.Write("Bytes lus (en hexadécimal) : ");
    foreach (byte b in readSettings)
        Console.Write($"{b:X2} "); // :X2 formate le byte en deux chiffres hexadécimaux

    Console.WriteLine();
}
else
{
    Console.WriteLine($"Erreur : Le fichier binaire '{binaryDataPath}' n’a pas été trouvé.");
}

Ces méthodes sont super pratiques pour sauvegarder des petits bouts de données binaires, genre pour cacher des petites images ou des objets sérialisés.

6. Gérer les fichiers sur le disque

La classe File propose aussi des méthodes pour gérer les fichiers sur le disque.

Vérifier l’existence d’un fichier : File.Exists(path) Renvoie true si le fichier existe à l’emplacement donné, et false sinon. C’est super conseillé d’utiliser cette méthode avant de lire, supprimer ou faire d’autres opérations qui pourraient planter si le fichier n’existe pas.

string myFileToCheck = "report.txt";
// On le crée d’abord pour l’exemple
File.WriteAllText(myFileToCheck, "Rapport de test.");

if (File.Exists(myFileToCheck))
{
    Console.WriteLine($"Le fichier '{myFileToCheck}' a été trouvé.");
    // Maintenant tu peux lire, supprimer, etc. sans souci
}
else
{
    Console.WriteLine($"Le fichier '{myFileToCheck}' n’a pas été trouvé.");
}

Supprimer un fichier : File.Delete(path) supprime définitivement le fichier du disque. Fais super gaffe, c’est irréversible !

string fileToDelete = "temp_file.txt";
// On crée le fichier pour l’exemple
File.WriteAllText(fileToDelete, "Ce fichier va être supprimé.");

if (File.Exists(fileToDelete))
{
    File.Delete(fileToDelete);
    Console.WriteLine($"Le fichier '{fileToDelete}' a été supprimé avec succès.");
}
else
{
    Console.WriteLine($"Le fichier '{fileToDelete}' n’existe plus ou a déjà été supprimé.");
}

7. Exceptions lors du travail avec les fichiers

Travailler avec les fichiers, c’est toujours interagir avec l’OS et des ressources externes, donc c’est potentiellement fragile.

Gère les exceptions (erreurs) ! Quand tu bosses avec les fichiers, plein de trucs peuvent mal tourner, et ton programme doit savoir gérer ça proprement, pas juste "planter". Les cas classiques :

  • FileNotFoundException : Le fichier que tu veux utiliser n’existe pas à l’emplacement donné.
  • DirectoryNotFoundException : Le dossier où tu veux créer ou trouver le fichier n’existe pas.
  • UnauthorizedAccessException : Ton programme n’a pas les droits pour lire, écrire ou supprimer le fichier/dossier (genre fichier système ou zone protégée).
  • IOException : Erreur générale d’entrée/sortie, souvent quand le fichier est déjà ouvert ailleurs et bloqué, ou pas assez de place sur le disque.

Utilise toujours le bloc try-catch pour bosser avec les fichiers en sécurité. Ça permet de "choper" l’erreur et de réagir (genre afficher un message à l’utilisateur, écrire dans un log).

string sensitiveFilePath = "secret_data.txt";

try
{
    // Essaye de lire un fichier qui n’existe peut-être pas ou auquel t’as pas accès
    string secretContent = File.ReadAllText(sensitiveFilePath);
    Console.WriteLine($"Contenu secret lu : {secretContent}");
}
catch (FileNotFoundException) // Erreur précise : fichier non trouvé
{
    Console.WriteLine($"Erreur : Le fichier '{sensitiveFilePath}' n’a pas été trouvé. Vérifie le chemin.");
}
catch (IOException ex) // Erreur générale d’E/S (genre fichier bloqué)
{
    Console.WriteLine($"Erreur d’E/S avec le fichier '{sensitiveFilePath}' : {ex.Message}");
}
catch (Exception ex) // Toute autre erreur inattendue
{
    Console.WriteLine($"Une erreur inattendue est survenue : {ex.Message}");
}

8. Quand System.IO.File n’est pas le meilleur choix ?

Même si la classe File est super polyvalente, il y a des cas où ce n’est pas optimal ou même possible :

Fichiers énormes (dizaines+ de Go) : Les méthodes ReadAllText()/ReadAllBytes() chargent tout le fichier en mémoire. Pour des fichiers énormes, ça va causer une OutOfMemoryException. Dans ces cas, File.ReadLines() (pour le texte) ou l’approche directe avec les streams (FileStream) est nécessaire pour lire/écrire par morceaux. (On verra les streams dans la prochaine conf).

Contrôle fin sur l’accès au fichier : Si tu veux un contrôle très précis sur comment le fichier est ouvert (genre accès exclusif pour que personne d’autre ne puisse lire/écrire, ou au contraire accès partagé en lecture), File ne propose pas ce niveau de détail. Il faut passer par les classes de streams plus bas niveau.

Opérations asynchrones : Pour les applis très performantes qui doivent faire des opérations fichiers sans bloquer le thread principal (genre sur un serveur web), il faut des méthodes asynchrones (genre ReadAllTextAsync()), qui sont aussi basées sur les streams.

Lecture/écriture partielle : Si tu veux lire juste une partie du fichier à un offset précis ou écrire au milieu d’un fichier existant, les méthodes de File ne conviennent pas. Il faut un accès direct au stream du fichier.

9. Résumé

Pourquoi System.IO.File est si populaire ?

  • Simplicité et concision : Ses méthodes statiques permettent de faire des trucs compliqués en une ou deux lignes. Ça simplifie grave le dev et rend le code plus lisible.
  • Gestion automatique des ressources : File s’occupe d’ouvrir et fermer les fichiers à chaque opération, t’évitant de gérer ça à la main (ce qui cause souvent des bugs).
  • Polyvalence pour les tâches courantes : Pour la plupart des opérations classiques sur des fichiers texte ou binaires de petite/moyenne taille, File suffit largement.
  • Très répandu : Dans la plupart des cas pratiques et en entretien, on s’attend à ce que tu saches utiliser les méthodes de la classe File.
  • Complexité cachée : Toutes les méthodes sont faites pour encapsuler la logique compliquée d’interaction avec l’OS, te donnant une interface propre et claire.

Questions fréquentes et précisions

Quelle est la taille max de fichier pour File.ReadAllText() ?
Pour les fichiers jusqu’à quelques dizaines de méga (< 100 Mo), en général aucun souci. Si le fichier est plus gros (centaines de Mo, gigas), utiliser File.ReadAllText() peut faire exploser la RAM (exception OutOfMemoryException). Dans ces cas, il vaut mieux utiliser File.ReadLines() pour lire ligne par ligne ou des outils plus avancés pour le streaming, on en parlera plus tard.

On peut créer/écrire un fichier dans un dossier qui n’existe pas ?
Non. Les méthodes File.WriteAllText(), File.WriteAllBytes() et autres ne créent pas les dossiers parents automatiquement. Si tu mets un chemin genre C:\MyAppData\Logs\current.log et que les dossiers MyAppData ou Logs n’existent pas, tu auras une DirectoryNotFoundException. Il faut d’abord t’assurer que tous les dossiers existent, avec les méthodes de la classe System.IO.Directory (genre Directory.CreateDirectory("myfolder")).

Comment connaître la date de création, de modif ou la taille d’un fichier ?
Pour avoir plus d’infos sur un fichier, genre date de création, date de dernière modif, taille, attributs (caché, lecture seule, etc.), utilise la classe System.IO.FileInfo. Elle propose plein de propriétés utiles.

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