1. Intro
Quand tu bosses avec des fichiers via FileStream ou d'autres classes de stream, c'est super important de piger à l'avance ce qui va arriver au fichier quand tu vas essayer de l'ouvrir. Souvent, le fichier existe déjà, et tu veux soit ajouter des nouvelles données sans perdre l'ancien contenu, soit carrément tout écraser. Parfois, le fichier n'existe pas encore, et tu veux juste le lire sans risquer de créer un fichier vide par accident.
Par exemple, si tu codes un carnet de notes quotidien, ton but c'est d'ajouter des nouvelles entrées à la fin du fichier existant, en gardant tout ce qui a été écrit avant. Donc tu dois ouvrir le fichier en mode ajout. Dans un autre cas — genre tu as un fichier de log qui doit être recréé à chaque lancement de l'appli pour ne pas mélanger les anciennes données — là tu veux ouvrir le fichier de façon à ce qu'il soit vidé ou créé à neuf s'il n'existe pas. Et si tu veux juste lire un fichier existant, tu veux sûrement t'assurer que tu ne vas pas créer un nouveau fichier s'il n'existe pas, sinon tu risques de te retrouver avec un fichier vide là où il ne devrait pas y en avoir.
Tous ces scénarios — ajout, écrasement, lecture sans création — sont gérés en C# via des modes d'ouverture spéciaux, définis par l'énum System.IO.FileMode. Chaque mode contrôle le comportement à l'ouverture ou à la création du fichier, pour que tu puisses vraiment piloter ce qui se passe quand tu bosses avec.
2. L'énum FileMode — tous les modes expliqués simplement
Voici les valeurs principales de l'énum FileMode :
| Valeur | Description | Si le fichier existe | Si le fichier n'existe pas |
|---|---|---|---|
|
Crée un nouveau fichier. Si le fichier existe déjà — lève une exception | Erreur | OK, fichier créé |
|
Crée un nouveau fichier si absent, ou écrase l'existant | Écrase | OK, crée |
|
Ouvre un fichier existant. Si le fichier n'existe pas — exception | OK, ouvre | Erreur |
|
Ouvre si existe, sinon crée un nouveau | OK, ouvre | OK, crée |
|
Ouvre un fichier existant et vide son contenu (tout est effacé) | OK, vide le fichier | Erreur |
|
Ouvre le fichier pour ajouter à la fin, sinon crée un nouveau | OK, ajoute à la fin | OK, crée |
Illustration : Scénarios de comportement
flowchart TD
Start[Début]
A{Le fichier existe ?}
B1[Ouvrir pour ajout]
B2[Créer un nouveau fichier]
B3[Écraser le fichier]
B4[Ouvrir le fichier]
B5[Erreur : fichier introuvable]
B6[Erreur : fichier existe déjà]
Start --> A
A --Append, OpenOrCreate--> B1
A --Create, Truncate--> B3
A --Open, Truncate--> B4
A --CreateNew--> B6
A --Create, OpenOrCreate, Append--> B2
A --Open, Truncate--> B5
3. Exemples d'ouverture de fichiers dans différents modes
On va tester tout ça en pratique avec notre mini-appli qu'on développe tout au long du cours. Imaginons qu'on a un fichier texte où on écrit des messages de bienvenue et la date. On va voir trois scénarios classiques :
- A. Création d'un nouveau fichier (CreateNew)
- B. Écrasement du fichier (Create)
- C. Ajout de lignes à la fin du fichier (Append)
Créer un nouveau fichier (FileMode.CreateNew)
Si le fichier existe déjà, ce mode garantit que tu ne pourras pas le recréer : le programme va lever une IOException. C'est parfait si tu ne veux pas perdre de données ou écraser des fichiers d'autres personnes par erreur.
using System;
using System.IO;
string filePath = "greeting.txt";
// On tente de créer un nouveau fichier — s'il existe déjà, exception !
try
{
var stream = new FileStream(filePath, FileMode.CreateNew, FileAccess.Write);
var writer = new StreamWriter(stream);
writer.WriteLine("Salut ! C'est la première entrée.");
writer.WriteLine($"Date : {DateTime.Now}");
Console.WriteLine("Fichier créé avec succès.");
writer.Close();
}
catch (IOException)
{
Console.WriteLine($"Le fichier '{filePath}' existe déjà ! On ne va pas l'écraser.");
}
À noter : si tu lances ce code une deuxième fois — le catch va s'activer, les données ne seront pas effacées.
Écraser un fichier (FileMode.Create)
Ce mode ne fait pas dans la dentelle : si le fichier existe, il est vidé. Sinon, il est créé. Pratique quand tu veux repartir "à zéro" à chaque fois. Par exemple, pour sauvegarder un rapport.
using System;
using System.IO;
string filePath = "greeting.txt";
// Création ou écrasement complet du fichier
var stream = new FileStream(filePath, FileMode.Create, FileAccess.Write);
var writer = new StreamWriter(stream);
writer.WriteLine("Salut ! J'ai complètement mis à jour le fichier :)");
writer.WriteLine($"Mis à jour : {DateTime.Now}");
Console.WriteLine("Fichier créé ou écrasé.");
writer.Close();
Lance ce code plusieurs fois — il n'y aura toujours que les dernières lignes dans le fichier. Tout l'ancien contenu disparaît.
Ajout à la fin du fichier (FileMode.Append)
Mode parfait pour les logs, journaux d'événements, suivi de visites, etc. Si le fichier n'existe pas — il est créé. S'il existe — les données sont ajoutées à la fin.
using System;
using System.IO;
string filePath = "greeting.txt";
// Ajout d'une nouvelle ligne à la fin du fichier
var stream = new FileStream(filePath, FileMode.Append, FileAccess.Write);
var writer = new StreamWriter(stream);
writer.WriteLine($"Encore un message de bienvenue ! Date : {DateTime.Now}");
Console.WriteLine("Nouvelle ligne ajoutée à la fin du fichier.");
writer.Close();
Teste ce code plein de fois. Le fichier va grossir, chaque nouvelle entrée sera tout en bas.
4. Comment choisir le mode d'ouverture ? Conseils pratiques
Scénarios de la vraie vie :
- Logs : quasi toujours Append. Perdre les logs à cause d'un écrasement — c'est la galère pour l'admin et un cadeau pour le méchant.
- Export de rapport : souvent Create, pour éviter d'encombrer le dossier avec des vieilles versions.
- Dump de données critiques : là, CreateNew est top. Si le fichier existe — erreur, on ne touche à rien.
- Lecture de fichier : pas besoin de mode création, utilise FileMode.Open — si le fichier n'existe pas, c'est qu'il y a un souci.
Quand tu codes en C#, tu utilises souvent les méthodes statiques de la classe File, qui choisissent le bon mode pour toi. Par exemple, File.AppendAllText bosse toujours avec Append, et File.WriteAllText — avec Create.
5. Modes de fichiers et pièges à éviter
Quelques pièges à connaître :
Si tu ouvres un fichier avec FileMode.Create ou FileMode.Truncate, tout le contenu sera effacé. Fais gaffe — même les pros se sont déjà fait avoir par une perte de données accidentelle.
Si tu essaies d'ouvrir un fichier inexistant avec FileMode.Open ou FileMode.Truncate, tu auras une FileNotFoundException. Pense à vérifier que le fichier existe avec File.Exists(path).
Avec le mode Append tu peux seulement écrire. Si tu veux lire et écrire, regarde d'autres modes (OpenOrCreate + le bon FileAccess).
Exemple : Lecture et écriture
Parfois tu veux lire et écrire dans le même fichier (genre tu ouvres un compte bancaire — tu veux déposer et vérifier le solde). Utilise FileMode.OpenOrCreate :
using System.IO;
string filePath = "balance.txt";
// Ouvre le fichier pour lecture et écriture ; sinon crée-le
var stream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
// Ici tu peux lire et écrire
6. Astuces utiles
Modes d'ouverture de fichier
graph TD
A[Demander le fichier] --> B[Choisir le mode]
B --> C1[CreateNew] -->|Si le fichier existe| D1[Erreur]
C1 -->|Fichier absent| E1[Créer]
B --> C2[Create] -->|Toujours| F1[Créer/Écraser]
B --> C3[Open] -->|Fichier existe| G1[Ouvrir]
C3 -->|Fichier absent| D1
B --> C4[OpenOrCreate] -->|Fichier existe| G1
C4 -->|Fichier absent| E1
B --> C5[Append] -->|Fichier existe| H1[Ouvrir pour ajout]
C5 -->|Fichier absent| E1
B --> C6[Truncate] -->|Fichier existe| I1[On vide]
C6 -->|Fichier absent| D1
Tableau récap des modes d'ouverture
| FileMode | Fichier existe | Fichier N'existe PAS | Accès aux données | Efface l'ancien contenu ? |
|---|---|---|---|---|
|
Exception | Crée un nouveau | Écrit | N/A |
|
Écrase | Crée un nouveau | Écrit | Oui |
|
Ouvre | Exception | Lit/écrit | Non |
|
Ouvre | Crée un nouveau | Lit/écrit | Non |
|
Vide | Exception | Écrit | Oui |
|
Ouvre pour écrire à la fin | Crée un nouveau | Écrit seulement | Non (ajoute) |
Comparaison avec les méthodes haut niveau de la classe File
- File.WriteAllText(path, text) → utilise FileMode.Create en interne, donc le fichier sera écrasé.
- File.AppendAllText(path, text) → utilise le mode Append, tout sera ajouté à la fin.
- File.ReadAllText(path) → ouvre le fichier en lecture (FileMode.Open).
Parfois ces méthodes suffisent, mais bosser avec FileStream et choisir le mode explicitement te donne un contrôle total.
Spécificités selon l'OS
Souvent, les devs oublient qu'en Windows, un fichier ouvert par un autre process en écriture peut être inaccessible — une tentative d'accès va planter. Donc c'est super important d'utiliser le paramètre FileShare pour gérer l'accès partagé (on en parlera plus en détail dans une prochaine conf). Selon l'OS, les mécanismes de verrouillage et de droits peuvent varier, mais le concept des modes d'ouverture reste universel.
GO TO FULL VERSION