Académique Documents
Professionnel Documents
Culture Documents
: LES FICHIERS
Fichier
Un fichier (angl.: file) est un ensemble structuré de données stocké en général sur un support externe
(usb, disque dur, disque optique, bande magnétique, ...).
Nous vous proposons ici d'étudier les fonctions permettant au programme d'échanger des informations
avec des "fichiers''
En C, comme d'ailleurs dans d'autres langages, tous les périphériques, qu'ils soient d'archivage
(disque,usb , . . . ) ou de communication (clavier, écran, imprimante,...), peuvent être considérés comme
des fichiers.
- l'accès séquentiel consiste à traiter les informations "séquentiellement", c'est-à-dire dans l'ordre
où elles apparaissent (ou apparaîtront) dans le fichier, les enregistrements sont mémorisés
consécutivement dans l'ordre de leur entrée et peuvent seulement être lus dans cet ordre
- - l'accès direct consiste à se placer immédiatement sur l'information souhaitée, sans avoir à
parcourir celles qui la précèdent.
Fichier séquentiel
Les fichiers séquentiels que nous allons considérer dans ce cours auront la propriété suivante:
* Les fichiers se trouvent ou bien en état d'écriture ou bien en état de lecture ; nous ne pouvons pas
simultanément lire et écrire dans le même fichier.
Fichiers standards
Il existe deux fichiers spéciaux qui sont définis par défaut pour tous les programmes:
En général, stdin est lié au clavier et stdout est lié à l'écran, c.-à-d. les programmes lisent leurs données
au clavier et écrivent les résultats sur l'écran.
CRÉATION SÉQUENTIELLE D'UN FICHIER
Voici un programme qui se contente d'enregistrer séquentiellement dans un fichier une suite de
nombres entiers qu'on lui fournit au clavier.
#include <stdio.h>
int main(void)
{
char nomfich[21] ;
int n ;
FILE * sortie ;
printf ("nom du fichier à créer : ") ;
scanf ("%20s", nomfich) ;
sortie = fopen (nomfich, "w") ;
do {
printf ("donnez un entier : ") ;
scanf ("%d", &n) ;
if (n) fwrite(&n, sizeof(int), 1, sortie) ;
}
while (n) ;
fclose (sortie) ;
return 0 ;
}
La déclaration : FILE * sortie signifie que sortie est un pointeur sur un objet de type FILE.
La fonction fopen est ce que l'on nomme une fonction d'ouverture de fichier. Elle possède deux
arguments :
- le nom du fichier concerné, fourni sous forme d'une chaîne de caractères; ici, nous avons prévu
que ce nom ne dépassera pas 20 caractères (le chiffre 21 tenant compte du caractère \0);
notez qu'en général ce nom pourra comporter une information (chemin, répertoire,...)
permettant de préciser l'endroit où se trouve le fichier.
- une indication, fournie elle aussi sous forme d'une chaîne, précisant ce que l'on souhaite faire
avec ce fichier.
Ici, on trouve w (abréviation de write) qui permet de réaliser une "ouverture en écriture". Plus
précisément, si le fichier cité n'existe pas, il sera créé par fopen.
fwrite (&n, sizeof(int), 1, sortie);
Notez que, d'une manière générale, fwrite permet de transférer plusieurs blocs consécutifs de même
taille à partir d'une adresse donnée.
Enfin, la fonction fclose réalise ce que l'on nomme une "fermeture" de fichier. Elle force l'écriture sur
disque du tampon associé au fichier
Remarque :
1) On emploie souvent le terme flux (en anglais stream) pour désigner un pointeur sur une structure de
type FILE. Ici, par exemple, sortie est un flux que la fonction fopen aura associé à un certain fichier.
D'une manière générale, par souci de simplification, lorsque aucune ambiguïté ne sera possible, nous
utiliserons souvent le mot fichier à la place de flux
2) fopen fournit un pointeur nul en cas d'impossibilité d'ouverture du fichier. Ce sera le cas, par
exemple, si l'on cherche à ouvrir en lecture un fichier inexistant ou encore si l'on cherche à créer un
fichier sur une disquette saturée.
3) fwrite fournit le nombre de blocs effectivement écrits. Si cette valeur est inférieure au nombre prévu,
cela signifie qu'une erreur est survenue en cours d'écriture. Cela peut être, par exemple, une disquette
pleine, mais cela peut se produire également lorsque l'ouverture du fichier s'est mal déroulée (et que
l'on n'a pas pris soin d'examiner le code de retour de fopen).
La lecture dans le fichier se fait par un appel de la fonction fread: Cette fonction lit les données depuis
un flux.
fread (&n, sizeof(int), 1, entree) dont les arguments sont comparables à ceux de fwrite.
Dans notre cas Mais la condition d'arrêt de la boucle est: feof (entree).
Celle-ci prend la valeur vrai (c'est-à-dire 1) lorsque la fin du fichier a été rencontrée.
Remarques:
do
{ fread (&n, sizeof(int), 1, entree) ;
if ( !feof(entree) ) printf ("\n%d", n) ;
}
while ( !feof(entree) ) ;
2) N'oubliez pas que le premier argument des fonctions fwrite et fread est une adresse. Ainsi, lorsque
vous aurez affaire à un tableau, il faudra utiliser simplement son nom (sans le faire précéder de &),
tandis qu'avec une structure il faudra effectivement utiliser l'opérateur & pour en obtenir l'adresse. Dans
ce dernier cas, même si l'on ne cherche pas à rendre son programme portable, il sera préférable
d'utiliser l'opérateur sizeof pour déterminer avec certitude la taille des blocs correspondants.
2) fread fournit le nombre de blocs effectivement lus (et non pas le nombre d'octets lus). Ce
résultat peut être inférieur au nombre de blocs demandés soit lorsque l'on a rencontré une fin
de fichier, soit lorsqu'une erreur de lecture est apparue. Dans notre précédent exemple
Exemple 2 : Problème
On se propose de créer un fichier qui est formé d'enregistrements contenant comme information le nom
d'une personne. Chaque enregistrement est donc constitué d'une seule rubrique, à savoir, le nom de la
personne.
L'utilisateur doit entrer au clavier le nom du fichier, le nombre de personnes et les noms des personnes.
Le programme se chargera de créer le fichier correspondant sur disque dur
Après avoir écrit et fermé le fichier, le programme va réouvrir le même fichier en lecture et afficher son
contenu, sans utiliser le nombre d'enregistrements introduit dans la première partie.
Solution en langage C
#include <stdio.h>
main()
{
FILE *P_FICHIER; /* pointeur sur FILE */
char NOM_FICHIER[30], NOM_PERS[30];
int C,NB_ENREG;
// Première partie :
//Créer et remplir le fichier */
printf("Entrez le nom du fichier à créer : ");
scanf("%s", NOM_FICHIER);
P_FICHIER = fopen(NOM_FICHIER, "w"); /* write */
printf("Nombre d'enregistrements à créer : ");
scanf("%d", &NB_ENREG);
C = 0;
while (C<NB_ENREG)
{
printf("Entrez le nom de la personne : ");
scanf("%s", NOM_PERS);
fprintf(P_FICHIER, "%s\n", NOM_PERS);
C++;
}
fclose(P_FICHIER);
// Deuxième partie :
// Lire et afficher le contenu du fichier */
P_FICHIER = fopen(NOM_FICHIER, "r"); /* read */
while (!feof(P_FICHIER))
{
fscanf(P_FICHIER, "%s\n", NOM_PERS);
printf("NOM : %s\n", NOM_PERS);
}
fclose(P_FICHIER);
return 0;
}
La fonction fopen
Cette fonction, de type FILE* ouvre un fichier et lui associe un flot de données. Sa syntaxe est :
fopen("nom-de-fichier","mode")
La valeur retournée par fopen est un flot de données. Si l'exécution de cette fonction ne se déroule pas
normalement, la valeur retournée est le pointeur NULL. Il est donc recommandé de toujours tester si la
valeur renvoyée par la fonction fopen est égale à NULL afin de détecter les erreurs (lecture d'un fichier
inexistant...).
Le premier argument de fopen est le nom du fichier concerné, fourni sous forme d'une chaîne de
caractères..
Le second argument, mode, est une chaîne de caractères qui spécifie le mode d'accès au fichier. Les
spécificateurs de mode d'accès diffèrent suivant le type de fichier considéré. On distingue :
les fichiers textes, pour lesquels les caractères de contrôle (retour à la ligne ...) seront
interprétés en tant que tels lors de la lecture et de l'écriture ;
les fichiers binaires, pour lesquels les caractères de contrôle se sont pas interprétés.
La fonction fclose
Elle permet de fermer le flot qui a été associé à un fichier par la fonction fopen. Sa syntaxe est :
fclose(flot)
où flot (pointeur)est le flot de type FILE* retourné par la fonction fopen correspondant.
La fonction fclose retourne un entier qui vaut zéro si l'opération s'est déroulée normalement (et une
valeur non nulle en cas d'erreur).
Pour l'écriture et la lecture des fichiers, nous allons utiliser les fonctions standard fprintf, fscanf, fputc et
fgetc qui correspondent à printf, scanf, putchar et getchar si nous indiquons stdout respectivement stdin
comme fichiers de sortie ou d'entrée
La fonction fprintf, analogue à printf, permet d'écrire des données dans un fichier. Sa syntaxe est :
ou bien
* <FP> est un pointeur du type FILE* qui est relié au nom du fichier cible.
* <Expr1>, <Expr2>, ... , <ExprN> représentent les rubriques qui forment un enregistrement et dont les
valeurs respectives sont écrites dans le fichier.
* <Form1>, <Form2>, ... , <FormN> représentent les spécificateurs de format pour l'écriture des
différentes rubriques
Exemple :
Remarque
L'instruction
fprintf(stdout, "Bonjour\n");
est identique à
printf("\Bonjour\n");
Attention !
Notez que fprintf (et printf) écrit toutes les chaînes de caractères sans le symbole de fin de chaîne '\0'.
Dans les fichiers texte, il faut ajouter le symbole de fin de ligne '\n' pour séparer les données.
ou bien
fscanf(<FP>,"<Form1>\n<Form2>\n...\n<FormN>\n", <Adr1>, <Adr2>, ... , <AdrN>);
* <FP> est un pointeur du type FILE* qui est relié au nom du fichier à lire.
* <Adr1>, <Adr2>, ... , <AdrN> représentent les adresses des variables qui vont recevoir les valeurs des
différentes rubriques d'un enregistrement lu dans le fichier.
* <Form1>, <Form2>, ... , <FormN> représentent les spécificateurs de format pour la lecture des
différentes rubriques (voir chapitre 4.4.).
Exemple :
Remarque
L'instruction
fputc transfère le caractère indiqué par <C> dans le fichier référencé par <FP> et avance la position de
la tête de lecture/écriture au caractère suivant.
* <FP> est un pointeur du type FILE* qui est relié au nom du fichier cible.
<C> représente une variable du type int qui peut accepter une valeur numérique de 0 à 255 ou le
symbole de fin de fichier EOF.
Remarque
L'instruction
fputc('a', stdout);
est identique à
putchar('a');
b) Lire un caractère dans un fichier séquentiel - fgetc
fgetc fournit comme résultat le prochain caractère du fichier référencé par <FP> et avance la position de
la tête de lecture/écriture au caractère suivant. A la fin du fichier, fgetc retourne EOF
<C> représente une variable du type int qui peut accepter une valeur numérique de 0 à 255 ou le
symbole de fin de fichier EOF.
<FP> est un pointeur du type FILE* qui est relié au nom du fichier à lire.
Remarque
L'instruction
C = fgetc(stdin);
est identique à
C = getchar();
Lors de la fermeture d'un fichier ouvert en écriture, la fin du fichier est marquée automatiquement par le
symbole de fin de fichier EOF (End Of File). Lors de la lecture d'un fichier, les fonctions
finfichier(<Nom>) respectivement feof(<FP>) nous permettent de détecter la fin du fichier:
feof( <FP> );
feof retourne une valeur différente de zéro, si la tête de lecture du fichier référencé par <FP> est arrivée
à la fin du fichier; sinon la valeur du résultat est zéro.
<FP> est un pointeur du type FILE* qui est relié au nom du fichier à lire.
Pour que la fonction feof détecte correctement la fin du fichier, il faut qu'après la lecture de la
dernière donnée du fichier, la tête de lecture arrive jusqu'à la position de la marque EOF. Nous
obtenons cet effet seulement si nous terminons aussi la chaîne de format de fscanf par un retour à la
ligne '\n' (ou par un autre signe d'espacement).
Exemple
Une boucle de lecture typique pour lire les enregistrements d'un fichier séquentiel référencé par un
pointeur FP peut avoir la forme suivante:
while (!feof(FP))
{
fscanf(FP, "%s\n ... \n", NOM, ... );
...
}
Exemple
#include <stdio.h>
#include <stdlib.h>
main()
{
FILE *FP;
FP = fopen("C:\\AUTOEXEC.BAT", "r");
if (!FP)
{
printf("Impossible d'ouvrir le fichier\n");
exit(-1);
}
while (!feof(FP))
putchar(fgetc(FP));
fclose(FP);
return 0;
}
Dans une chaîne de caractères constante, il faut indiquer le symbole '\' (back-slash) par '\\', pour qu'il ne
soit pas confondu avec le début d'une séquence d'échappement (p.ex: \n, \t, \a, ...).
C
Ouverture en écriture <FP> = fopen(<Nom>,"w");
Ouverture en lecture <FP> = fopen(<Nom>,"r");
Fermeture fclose(<FP>);
Fonction fin de fichier feof(<FP>)
fprintf(<FP>,"...",<Adr>);
Ecriture
fputc(<C>, <FP>);
fscanf(<FP>,"...",<Adr>);
Lecture
<C> = fgetc(<FP>);