Un fichier est une unité de stockage d’informations sur un support (clé USB, disque dur, SSD, …). Un fichier peut contenir plusieurs types de données :
fichier texte, lisible par un humain (comme les fichiers .txt)
fichiers binaires, données codées, lisible par un programme (comme i, fichier .exe ou une image .jpg)
En langage C, on distingue donc deux formes de fichiers :
Les fichiers textes
Ils sont constitués de caractères, terminés par un caractère de fin de ligne \n en linux, \r\n sur Windows.
Les fichiers binaires
Les données sont enregistrées sous leur forme brute (= non transformée en caractères)
Pourquoi utiliser des fichiers
Jusqu’à maintenant et comme expliqué dans le cours 09 - Allocation dynamique lorsque vous écrivez un programme en C, les données comme les tableaux, les variables, les structures sont stockées dans la mémoire vive(RAM) et elle disparaissent dès que le programme se termine.
Les fichiers permettraient alors de
sauvegarder des données avant la fin du programme pour pouvoir les réutiliser plus tard sans qu’elles ne soient détruite à la fin du programme.
échanger des informations entre différents programmes
stocker de grande quantités de données qui ne peuvent pas toujours être gardées en mémoire.
Exemple :
Un éditeur de texte sauvegarde votre saisie dans un fichier .txt.
Une application de gestion sauvegarde vos données dans un fichier .dat ou .csv.
Types d’accès aux fichiers
Avant de commencer à manipuler des fichiers, faut-il déjà savoir comprendre comment on peut y accéder…
Accès séquentiel
On lit/écrit les données les unes après les autres dans l’ordre. On peut voir ceci comme lire un roman page par page. Ce genre d’accès est très utile pour les fichiers texte.
Accès direct (ou aléatoire)
On peut accéder à une position donnée dans le fichier. Bien plus utile pour les fichiers binaires. Par exemple ouvrir une vidéo et avancer à une certaine durée.
Les fichiers et le système d’exploitation
Le système d’exploitation gère les fichiers grâce aux informations suivantes :
Le nom du fichier
Le chemin d’accès du fichier
Le type de fichier (texte, binaire, exécutable, …)
Les droits d’accès(lecture, écriture, exécution)
Remarque
En langage C, pour travailler avec un fichier, on ne passe pas directement par son nom. On utilise ce qu’on appelle un pointeur de fichier qui permet de faire le lien entre le programme C et le fichier fourni par le système d’exploitation.
Cycle de vie d’un fichier en C
Lorsqu’on veut utiliser un fichier, il y a plusieurs étapes logiques à suivre :
Ouverture du fichier : le programme demande au système d’exploitation de préparer le fichier pour lecture/écriture.
Traitement du fichier : lecture ou écriture des données.
Fermeture du fichier : libération des ressources et sauvegarde correcte.
Les fichiers texte
En C, manipuler des fichiers permet de lire et écrire des données sur le disque au lieu de seulement utiliser la mémoire vive. Les fonctions principales se trouvent dans la bibliothèque standard <stdio.h>.
Ouvrir un fichier
Pour ouvrir un fichier en langage C on utilise la fonction fopen dont le prototype est le suivant :
Pensez à vérifier que le fichier c’est bien ouvert. C’est les mêmes sortes de vérifications que l’on faisait dans le cours 09 sur les allocations dynamiques.
if(!fichier) { // Gestion en cas d'erreur printf(...); return 1;}
Les différents modes d’ouverture d’un fichier :
Mode
Description
Précision
"r"
Lecture
Le fichier doit exister
"w"
Écriture
Créer le fichier si il n'existe pas ou écrase le contenu existant
"a"
Ajout
Ajoute à la fin du fichier
"r+"
Lecture et écriture
"w+"
Lecture et écriture
Écrase le fichier
"a+"
Lecture et ajout
Exemple :
// Ouverture d'un fichier en écritureFILE* fichier = fopen("fichier.txt", "w");if(!fichier){ printf("Le fichier n'a pas été ouvert...\n"); return 1;}
Écrire dans un fichier
Pour écrire dans un fichier en programmation C il existe deux fonctions fprintf ou alors fputs. Regardons le comportement des deux fonctions.
La fonction fprintf
La fonction fprintfest une fonction utilisée pour écrire des données formatées dans un flux, typiquement un fichier.
stream le flux dans lequel on souhaite écrire : fichier ouvert avec fopen ou même stdout pour afficher à l’écran.
chaine chaîne de caractères à afficher, avec du formatage si il faut introduire des variables, comme avec printf.
... c’est le nombre d’arguments variables selon si vous avez utilisé du formatage.
Elle retourne un entier, qui est le nombre de caractères écrits, si il y a une erreur, la fonction renvoie un nombre négatif !
Exemple :
// On a ouvert le fichierfprintf(fichier, "Bonjour le monde");
On écrit “Bonjour le monde”suivit d’un retour à la ligne \n dans le fichier pointé par le pointeur fichier.
Remarque
Les deux syntaxes suivantes sont strictement équivalentes :
printf("Bonjour le monde");
fprintf(stdout, "Bonjour le monde");
La fonction fputs
La fonction fputs permet d’écrire une chaîne de caractères sans format dans un flux. Elle est plus simple d’uitilisation que fprintf mais elle ne permet pas de faire du formatage…
Comme scanf, fscanflit en fonction des espaces (espace, tabulation, retour à la ligne).
Toujours utiliser l’adresse des variables (&age, &height) pour stocker les valeurs.
Retourne le nombre d’éléments lus, utile pour vérifier la lecture correcte.
Pour lire une ligne entière sans formatage, fgets est souvent préférable.
La fonction fgets
Copie de la partie de cours [[07 - Chaînes de caractères#la-fonction-fgets|La fonction fgets]]
La fonction fgets permet de récupérer une chaîne de caractères à partir d’un flux (le plus souvent, stdin).
Prototype de la fonction
#include <stdio.h>char *fgets(char *var, int t, FILE *stream);
var la variable qui va permettre de stocker la chaîne de caractères lue.
t la taille de la chaîne à stocker.
stream le flux sur lequel on récupère la chaîne (stdin, fichier, …)
Il faut savoir que la fonction fgets arrête la lecture lorsqu’elle rencontre \n, la fin du flux, ou alors après t-1 caractères lus (\0 le dernier caractère).
Warning
La fonction fgets inclus \n dans la chaîne lue si celle ci est rencontrée avant la limite.
Exemple :
// Lire une ligne dans le fichierchar ligne[100];fgets(ligne, 100, fichier); // lit une ligneprintf("%s", ligne);
La fonction fgetc
La fonction fgetc elle permet de lire un caractère depuis un flux (fichier par ex).
Prototype de la fonction fgetc
#include <stdio.h>int fgetc(FILE *stream);
stream : le flux à partir duquel lire (fichier ouvert avec fopen, stdin, etc.).
Retourne le caractère lu(sous forme de int), ou EOF si la fin du fichier est atteinte ou s’il y a une erreur.
Remarque
On utilise int pour pouvoir représenter tous les caractères et EOF (=−1).
Exemple :
On a un fichier test.txt qui contient bonjour, on le lit et on affiche un caractère par un caractère.
#include <stdio.h>int main() { FILE *f = fopen("test.txt", "r"); if (f == NULL) { printf("Erreur lors de l'ouverture du fichier\n"); return 1; } int c; while ((c = fgetc(f)) != EOF) { // Lire le fichier jusqu'à la fin putchar(c); // Afficher le caractère } fclose(f); // Fermeture du fichier return 0;}
Bonjour
Fermeture du fichier
La fonction fclose est essentielle en C pour fermer un flux ouvert(fichier). Chaque fois que tu ouvres un fichier avec fopen, il faut le fermer avec fclose pour libérer les ressources et s’assurer que tout le contenu est bien écrit.
Prototype de la fonction
#include <stdio.h>int fclose(FILE *stream);
stream le flux/fichier à fermer (retourné par fopen).
Retourne 0 si la fermeture s’est bien passée, EOF en cas d’erreur *(i.e. −1).
Les fichiers binaires
Mode d’ouverture
Mode
Description
Précision
"rb"
Lecture binaire
Le fichier doit exister
"wb"
Écriture binaire
Créer le fichier s'il n'existe pas ou écrase le contenu existant
"ab"
Ajout binaire
Ajoute à la fin du fichier
"r+b"
Lecture et écriture binaire
"w+b"
Lecture et écriture binaire
Écrase le fichier
"a+b"
Lecture et ajout binaire
Lecture
Pour lire dans une fichier binaire on utilise la fonction fread qui permet de lire des blocs de données depuis un fichier ouvert. Elle est souvent utilisée pour lire des données binaires, mais peut aussi être utilisée pour lire des structures.
ptr : Pointeur vers la zone mémoire où les données lues seront stockées.
size : Taille, en octets, de chaque élément à lire.
nbelem : Nombre d’éléments à lire.
stream : Pointeur vers le fichier ouvert en lecture (ou lecture/écriture).
Elle renvoie le nombre d’éléments lu qui peut être inférieur à nbelem si la fin du fichier est atteinte FEOF, ou si il y a une erreur.
Exemple :
On lit 5 entiers que l’on stocke dans un tableau.
#include <stdio.h>#include <stdlib.h>int main() { FILE *f = fopen("exemple.bin", "rb"); // ouverture en mode binaire lecture if (!f) { perror("Erreur ouverture fichier"); return 1; } int tab[5]; // lire 5 entiers size_t n = fread(tab, sizeof(int), 5, f); printf("Nombre d'éléments lus : %zu\n", n); for (size_t i = 0; i < n; i++) { printf("tab[%zu] = %d\n", i, tab[i]); } fclose(f); return 0;}
Warning
fread ne met pas de caractère nul à la fin si vous lisez du texte. Pour les chaînes de caractères, il faut gérer la terminaison soi-même.
Écrire
Pour écrire dans un fichier binaire, on utilise la fonction fwrite qui permet d’écrire des blocs de données dans un fichier ouvert. Elle est souvent utilisée pour écrire des données binaires, mais peut aussi être utilisée pour écrire des structures.