Gestion des fichiers en C : Maîtriser les E/S avec fopen, fprintf, fread et fseek
Gestion des fichiers en C
Ce tutoriel vous guide à travers les E/S de fichiers en C, couvrant les opérations standard et binaires avec des exemples pratiques clairs.
Un fichier est un conteneur logique sur le stockage d'un ordinateur qui conserve des données pour une utilisation à long terme.
Pourquoi utiliser des fichiers ?
- Les données persistent après la fin d'un programme, évitant la perte d'informations.
- De grands ensembles de données peuvent être stockés une fois et accédés rapidement via quelques commandes C.
- Les fichiers peuvent être déplacés entre ordinateurs sans modification.
Types de fichiers
En C, vous rencontrerez deux types de fichiers principaux :
- Fichiers texte
- Fichiers binaires
Fichiers texte
Les fichiers texte brut (ex. .txt) sont éditables avec n'importe quel éditeur de texte. Ils sont faciles à lire, maintenir et transférer mais occupent plus d'espace et offrent une sécurité minimale.
Fichiers binaires
Les fichiers binaires (souvent .bin) stockent les données comme des octets bruts (0 et 1). Ils sont compacts, non lisibles par l'homme, et offrent une meilleure intégrité et sécurité des données.
Opérations de base sur les fichiers
Quel que soit le type, la gestion de fichiers en C repose sur quatre opérations :
- Créer un nouveau fichier
- Ouvrir un fichier existant
- Fermer un fichier
- Lire depuis ou écrire dans un fichier
Préparation d'un pointeur de fichier
Toutes les opérations sur fichiers nécessitent un pointeur FILE * pour référencer le fichier ouvert :
FILE *fptr;
Ouverture de fichiers : Création et édition
La fonction fopen() (déclarée dans stdio.h) ouvre un fichier et retourne un pointeur FILE *. Sa syntaxe est :
fptr = fopen("filename", "mode");
Exemples d'utilisation :
fopen("E:\\cprogram\\newprogram.txt", "w");
fopen("E:\\cprogram\\oldprogram.bin", "rb");
Explication :
newprogram.txtest créé (s'il est absent) et ouvert en écriture avec le mode'w', qui écrase tout contenu existant.oldprogram.binest ouvert en lecture binaire seule avec le mode'rb'; toute tentative d'écriture échouera.
| Mode | Signification | Comportement si fichier absent |
|---|---|---|
r | Ouverture en lecture | Retourne NULL |
rb | Ouverture en lecture binaire | Retourne NULL |
w | Ouverture en écriture (écrasement) | Crée le fichier s'il est absent |
wb | Ouverture en écriture binaire (écrasement) | Crée le fichier s'il est absent |
a | Ouverture en ajout | Crée le fichier s'il est absent |
ab | Ouverture en ajout binaire | Crée le fichier s'il est absent |
r+ | Lecture et écriture | Retourne NULL |
rb+ | Lecture et écriture en binaire | Retourne NULL |
w+ | Lecture et écriture (écrasement) | Crée le fichier s'il est absent |
wb+ | Lecture et écriture en binaire (écrasement) | Crée le fichier s'il est absent |
a+ | Lecture et ajout | Crée le fichier s'il est absent |
ab+ | Lecture et ajout binaire | Crée le fichier s'il est absent |
Fermeture d'un fichier
Après toutes les opérations E/S, fermez toujours le fichier avec fclose() pour libérer les ressources et vider les tampons :
fclose(fptr);
E/S sur fichiers texte
Les fichiers texte sont gérés avec fprintf() et fscanf(), les équivalents fichier de printf() et scanf(). Ils nécessitent un pointeur FILE * comme premier argument.
Exemple 1 : Écrire dans un fichier texte
#include <stdio.h>
#include <stdlib.h>
int main() {
int num;
FILE *fptr;
// Ajustez le chemin pour votre OS
fptr = fopen("C:\\program.txt", "w");
if (fptr == NULL) {
printf("Erreur d'ouverture du fichier\n");
exit(EXIT_FAILURE);
}
printf("Entrez un nombre : ");
scanf("%d", &num);
fprintf(fptr, "%d", num);
fclose(fptr);
return 0;
}
Ce programme capture un entier de l'utilisateur et l'écrit dans program.txt.
Exemple 2 : Lire depuis un fichier texte
#include <stdio.h>
#include <stdlib.h>
int main() {
int num;
FILE *fptr;
fptr = fopen("C:\\program.txt", "r");
if (fptr == NULL) {
printf("Erreur d'ouverture du fichier\n");
exit(EXIT_FAILURE);
}
fscanf(fptr, "%d", &num);
printf("Valeur lue : %d\n", num);
fclose(fptr);
return 0;
}
L'exécution après le premier exemple affichera l'entier stocké.
Des utilitaires additionnels comme fgetc() et fputc() suivent le même schéma.
E/S sur fichiers binaires
Les fichiers binaires sont manipulés avec fwrite() pour l'écriture et fread() pour la lecture. Les deux fonctions acceptent quatre arguments : pointeur vers les données, taille de chaque élément, nombre d'éléments, et pointeur FILE *.
Écriture dans un fichier binaire
fwrite(addressData, sizeData, numberData, filePointer);
Exemple 3 : Écrire dans un fichier binaire avec fwrite()
#include <stdio.h>
#include <stdlib.h>
struct threeNum {
int n1, n2, n3;
};
int main() {
int i;
struct threeNum num;
FILE *fptr;
fptr = fopen("C:\\program.bin", "wb");
if (fptr == NULL) {
printf("Erreur d'ouverture du fichier\n");
exit(EXIT_FAILURE);
}
for (i = 1; i < 5; ++i) {
num.n1 = i;
num.n2 = 5 * i;
num.n3 = 5 * i + 1;
fwrite(&num, sizeof(struct threeNum), 1, fptr);
}
fclose(fptr);
return 0;
}
Lecture depuis un fichier binaire
La signature correspondante de fread() miroir fwrite() :
fread(addressData, sizeData, numberData, filePointer);
Exemple 4 : Lire depuis un fichier binaire avec fread()
#include <stdio.h>
#include <stdlib.h>
struct threeNum {
int n1, n2, n3;
};
int main() {
int i;
struct threeNum num;
FILE *fptr;
fptr = fopen("C:\\program.bin", "rb");
if (fptr == NULL) {
printf("Erreur d'ouverture du fichier\n");
exit(EXIT_FAILURE);
}
for (i = 1; i < 5; ++i) {
fread(&num, sizeof(struct threeNum), 1, fptr);
printf("n1: %d\tn2: %d\tn3: %d\n", num.n1, num.n2, num.n3);
}
fclose(fptr);
return 0;
}
Ce programme reproduit les données écrites dans l'Exemple 3.
Accès aléatoire avec fseek()
Lorsqu'un fichier contient de nombreux enregistrements, parcourir séquentiellement jusqu'à une entrée spécifique peut être inefficace. fseek() déplace le pointeur de fichier à une position arbitraire, permettant un accès direct.
Syntaxe
fseek(FILE *stream, long int offset, int whence);
stream: pointeur retourné parfopen().offset: nombre d'octets à déplacer.whence: point de départ –SEEK_SET,SEEK_CURouSEEK_END.
| Constante | Signification |
|---|---|
SEEK_SET | Le décalage commence au début du fichier. |
SEEK_CUR | Le décalage commence à la position actuelle du curseur. |
SEEK_END | Le décalage commence à la fin du fichier. |
Exemple 5 : Lecture en ordre inverse avec fseek()
#include <stdio.h>
#include <stdlib.h>
struct threeNum {
int n1, n2, n3;
};
int main() {
int i;
struct threeNum num;
FILE *fptr;
fptr = fopen("C:\\program.bin", "rb");
if (fptr == NULL) {
printf("Erreur d'ouverture du fichier\n");
exit(EXIT_FAILURE);
}
// Déplacement au dernier enregistrement
fseek(fptr, -sizeof(struct threeNum), SEEK_END);
for (i = 1; i < 5; ++i) {
fread(&num, sizeof(struct threeNum), 1, fptr);
printf("n1: %d\tn2: %d\tn3: %d\n", num.n1, num.n2, num.n3);
// Reculer de deux enregistrements (actuel + un de plus) pour lire l'entrée précédente
fseek(fptr, -2 * sizeof(struct threeNum), SEEK_CUR);
}
fclose(fptr);
return 0;
}
Cet extrait montre comment parcourir un fichier binaire en sens inverse, en partant du dernier enregistrement.
Langue C
- Maîtriser les opérations sur les fichiers Java avec java.io – Création, lecture, écriture et suppression
- Comprendre les Fichiers STL : La Colonne Vertébrale de l'Impression 3D
- Maîtriser les entrées/sorties de fichiers en Verilog : Ouvrir, Lire, Écrire et Fermer
- Maîtriser les entrées/sorties fichiers en C : Création, ouverture et gestion
- Comprendre les fichiers d'en-tête C : Types, utilisation et bonnes pratiques
- Maîtriser la gestion d'erreurs en C : Bonnes pratiques et techniques
- Maîtriser les entrées/sorties fichier en C++ : Lecture et écriture avec fstream
- Maîtriser la gestion des signaux en C++ : Interruption sécurisée et terminaison propre du programme
- Maîtriser la gestion d'exceptions en C# : stratégies et bonnes pratiques