Blog ENI : Toute la veille numérique !
💥 Un livre PAPIER acheté
= La version EN LIGNE offerte pendant 1 an !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. Langage C
  3. Introduction aux fichiers
Extrait - Langage C Maîtriser la programmation procédurale (avec exercices pratiques) (2e édition)
Extraits du livre
Langage C Maîtriser la programmation procédurale (avec exercices pratiques) (2e édition)
2 avis
Revenir à la page d'achat du livre

Introduction aux fichiers

Fichiers (type FILE*)

Voici quelques questions pour vous aider à synthétiser et retenir des contenus qui nous paraissent essentiels dans cette section :

Quel type permet d’ouvrir ou de créer un fichier ? Avec quelle fonction ?

Lors de l’ouverture d’un fichier à quoi correspondent les modes a, r et w ?

Comment obtenir un fichier binaire ?

Comment spécifier un chemin d’accès ?

Quelle fonction permet d’écrire dans un fichier binaire ?

Quelle fonction permet de lire dans un fichier binaire ?

Comment détecter la fin d’un fichier binaire ?

Comment se déplacer dans un fichier ?

Comment détecter la fin d’un fichier texte ?

Quelles sont les principales fonctions de lecture et d’écriture dans un fichier texte ?

Quelles sont les fonctions de lecture et d’écriture de texte formaté ?

Quels problèmes posent la sauvegarde sur fichier d’éléments dynamiques ?

Notions de base

1. Le type FILE*

Dans un programme C, un fichier est toujours une structure de type FILE définie dans la bibliothèque stdio.h et manipulée via son adresse par un pointeur FILE*. Pour utiliser un fichier dans un programme, ou une fonction du programme, la première chose à faire est de déclarer un FILE* :

#include <stdio.h> 
 
int main() 
{ 
FILE*f;  
    (...) 
    return 0; 
} 

2. Ouverture et fermeture d’un fichier

Dans la librairie standard stdio.h, la fonction :

FILE* fopen( const char* name ,const char* mode); 

permet d’ouvrir un fichier existant ou de créer un fichier. Cette fonction ouvre le fichier dont le nom comprenant le chemin d’accès est spécifié au premier paramètre et selon le mode donné par le second paramètre. Les deux sont des chaînes de caractères. Il y a six modes possibles : r, w, a, r+, w+, a+ et le caractère "b" ajouté ensuite permet de sélectionner une entrée/sortie en mode binaire.

Voici un tableau récapitulatif des différents modes possibles :

Mode

Accès

Positionnement en écriture

Si le fichier existe

Si le fichier n’existe pas

r

Lecture

au début

ouverture

erreur

w

a

Écriture

Écriture

au début

à la fin

initialisation

ouverture

création

création

r+

w+

a+

Lecture

et

écriture

au début

au début

à la fin

ouverture

initialisation

ouverture

erreur

création

création

Suffixe b : à ajouter pour les entrées/sorties binaires.

Attention, l’initialisation d’un fichier existant signifie qu’il est ramené à une taille nulle, c’est-à-dire que toutes les données qu’il contient sont perdues.

Pour refermer un fichier précédemment ouvert, la librairie stdio.h propose la fonction :

int fclose(FILE*); 

Cette fonction referme le fichier indiqué via le pointeur au paramètre p. Elle retourne EOF sur erreur et zéro sinon. EOF est une valeur sentinelle qui indique la fin du fichier.

Exemple d’ouverture/fermeture de fichier en mode binaire :

#define _CRT_SECURE_NO_WARNINGS // sous Visual Studio uniquement 
#include <stdio.h> 
 
int main() ...

Fichiers binaires

1. Écriture et lecture en mode binaire

L’utilisation des fichiers binaires repose sur deux fonctions uniquement : une pour l’écriture et une pour la lecture. Ces deux fonctions sont dans la librairie standard stdio.h.

Pour écrire (save) des données :

size_t        fwrite ( const void*, size_t, size_t, FILE* ); 

Cette fonction écrit sur le fichier spécifié en p4, p3 objets de taille p2 en octet, rangés à partir de l’adresse p1. Elle retourne le nombre d’objets effectivement écrits.

Pour lire (load) les données d’un fichier :

size_t        fread ( void*, size_t, size_t, FILE*); 

Soit p1, p2, p3, p4, les paramètres spécifiés dans la fonction.

Cette fonction lit au plus p3 objets de taille p2 en octet sur le fichier spécifié en p4 et les copie à l’adresse p1. Elle retourne le nombre d’objets effectivement lus.

Exemple d’utilisation :

#include <stdio.h>  
#include <stdlib.h>  
 
#define NB_POINT    10  
 
typedef struct point { 
  int x, y; 
}t_point; 
 
void    init(t_point t[]); 
void    affiche(t_point t[]); 
 
int main() 
{ 
  FILE* f; 
  t_point...

Écriture et lecture en mode texte

Certaines des fonctions présentées dans ce module sont également présentées dans le module sur les chaînes de caractères. Elles y sont utilisées avec les fichiers d’entrée-sortie standard stdin et stdout. Il s’agit maintenant de les employer plus largement avec toutes sortes de fichiers créés dans un programme. Il y a dans ce module d’autres exemples d’utilisation.

1. Détecter la fin d’un fichier : EOF et feof()

En mode texte surtout, détecter la fin d’un fichier est souvent nécessaire. Il y a deux méthodes. La première du fait de la valeur EOF et la seconde avec la fonction feof().

Le caractère de fin de fichier EOF -------     <stdio.h> 

La fin des fichiers texte et binaire est marquée par une valeur définie par une macro constante EOF déclarée dans stdio.h. Cette valeur vaut en général -1 mais elle peut varier d’un environnement à l’autre. Dans les tests qui l’utilisent, il est plus sûr de toujours utiliser EOF plutôt que -1.

La plupart des fonctions du mode texte utilisent la valeur EOF pour signifier la fin du fichier. Cette valeur est aussi utilisée comme retour d’erreur, par exemple pour la fonction fclose().

int        feof ( FILE*) -------     <stdio.h> 

Cette fonction retourne vrai si la position courante dans le fichier passé en paramètre est à la fin et faux sinon. Cette fonction peut être utilisée pour les deux modes, texte et binaire.

2. Lecture/écriture de caractères

int fgetc ( FILE*) ------- <stdio.h> 

Cette fonction retourne un caractère lu sur le fichier spécifié en paramètre et EOF en cas d’erreur ou de détection de la fin du fichier. La macro int getc(FILE*) en est une autre forme équivalente.

int fputc (int, FILE*) ------- <stdio.h> 

Cette fonction écrit sur le fichier spécifié en p2 le caractère spécifié en p1. Elle retourne le caractère p1, sinon en cas d’erreur elle retourne EOF.

Exemple d’utilisation

Le programme ci-dessous ouvre en lecture seule le fichier entree.txt....

Sauvegarde d’éléments dynamiques

1. Sauvegarder et récupérer un tableau dynamique

Lors d’une sauvegarde de données obtenues dynamiquement, la taille peut être sauvegardée au début ou à la fin du fichier mais ce n’est pas obligatoire. En revanche, lors du chargement des données, il est nécessaire d’allouer la mémoire nécessaire des variables auxquelles sont affectées les données du fichier. Par exemple :

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
typedef struct point{ 
    int x,y; 
}t_point; 
 
void    init        (t_point**t,int nb); 
void    affiche     (t_point t[],int nb); 
 
int main() 
{ 
FILE*f; 
t_point*data; 
t_point*recup=NULL; 
int nb; 
 
    srand(time(NULL)); 
    if (fopen_s(&f,"test.bin", "wb+")==0){  
        // allocation et initialisation d'un tableau dynamique 
        // de taille aléatoire 
        nb=1+rand()%20; 
        init(&data,nb); ...

Expérimentation : récapitulation sauvegardes binaires

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#include <string.h> 
 
// macro-constante pour la taille des tableaux statiques 
#define NBMAX 5 
 
// le type de data à sauvegarder et récupérer 
typedef struct 
{ 
     int x, y; 
}t_acteur; 
 
// pour tableau d'acteurs statique ou dynamique 
void    Init(t_acteur t[], int nb); 
void    Affiche(t_acteur t[], int nb); 
void    SaveTabStatic(char* nameFile, t_acteur t[]); 
void    LoadTabStatic(char* nameFile, t_acteur t[]); 
void    SaveTabDyn(char* nameFile, t_acteur t[], int nb); 
int         LoadTabDyn(char* nameFile, t_acteur** t); 
 
// tableau statique de pointeurs 
void    InitActeur(t_acteur* a); 
void    InitTabPtr(t_acteur* t[]); 
void    AfficheTabPtr(t_acteur* t[]); 
void    SaveTabPtr(char* nameFile, t_acteur* t[]); 
void    LoadTabPtr(char* nameFile, t_acteur* t[]); 
/************************************************************ 
*************************************************************/ 
int main() 
{ 
     t_acteur tabStat[NBMAX]; 
     t_acteur *tabDyn; 
     t_acteur* tabPtr[NBMAX]; 
     int nbmax; 
     srand((unsigned)time(NULL)); 
 
     // TABLEAU STATIQUE 
     printf("SEQUENCE TAB STATIQUE :\n"); 
     Init(tabStat, NBMAX); 
     Affiche(tabStat, NBMAX); 
 
     //Sauvegarde du tableau initialisé 
     SaveTabStatic("tabStatic.bin", tabStat); 
 
     // effacement du tableau : mise à 0 de tous les octets 
     memset(tabStat, 0, sizeof(t_acteur)*NBMAX); 
     Affiche(tabStat...

Mise en pratique : fichiers

Exercice 1

Dans un programme, ouvrir en lecture un fichier dont le nom est donné par l’utilisateur. Indiquer si l’opération a réussi. Si l’opération échoue, le fichier n’existe pas, le créer et indiquer le résultat. Faire tourner le programme une première fois, le fermer et le lancer une deuxième fois pour vérifier que le fichier a bien été créé et s’ouvre correctement. Aller sur le disque voir où le fichier se trouve. Ne pas oublier dans le programme de fermer le fichier quand il n’a plus besoin d’être ouvert.

Exercice 2

Écrire un programme qui ouvre ou crée un fichier dont le nom, l’emplacement et le mode sont entrés par l’utilisateur. Ne pas oublier de fermer le fichier lorsque cela a réussi et qu’un message a été transmis à l’utilisateur.

Exercice 3

Un programme crée un fichier qui se trouve dans un dossier nommé test dans le répertoire du programme. Vérifier que le fichier est bien sur le disque dur. Modifier le programme pour ouvrir le fichier en lecture uniquement et relancer le programme. Ne pas oublier de fermer le fichier.

Exercice 4

Avec le Bloc-notes créer un fichier qui est sauvé dans un répertoire distant du programme.

Par rapport au programme il faut remonter de trois niveaux et redescendre de quatre niveaux pour trouver le fichier. Écrire le programme qui ouvre le fichier et le referme.

Exercice 5

Écrire un programme qui demande à l’usager d’entrer des mots un à un, qui stocke ces mots à la fin d’un fichier texte, puis qui affiche le contenu du fichier complet. Initialement, le programme doit créer le fichier s’il n’existe pas, mais ne doit pas perdre son contenu s’il existe...