École Supérieure de Technologie
et d’Informatique
A.U. 2011/2012
Cours atelier de programmation avancée
Chapitre: Les fichiers binaires (Partie I : 10 pages)
1ère année LA ARS
Les fonctions d’écriture et de lecture binaire : fread et fwrite
Les fonctions d’écriture et de lecture formatée : fprintf, fscanf, fputs, fgets
Les fonctions d’écriture et de lecture mixtes : fputc, fgetc.
En C, un fichier est considéré comme une collection ordonnée d’octets. La notion
d’enregistrement n’existe plus.
On peut choisir entre deux manières de représenter (archiver) l’information dans un fichier :
(cid:1) Sous forme binaire : copier l’information dans le fichier telle qu’elle figure en
mémoire (fonction d’écriture dans le fichier: fwrite ; fonction de lecture à partir du
fichier : fread)
(cid:1) Sous forme formatée : exprimer l’information sous la forme d’une suite de caractères
(càd d’octets contenant des codes de caractères) (fonctions de lecture à partir d’un
fichier: fscanf, fgets ; fonctions d’écriture dans un fichier: fprintf, fputs).
Les fichiers créés en binaire ne peuvent être exploités que dans l’environnement dans lequel
ils ont été créés, ou pour le moins, dans un environnement utilisant le même codage.
La forme formatée est souvent utilisée pour « porter » des données d’un environnement à un
autre, et ce malgré le coût supplémentaire en temps induit par les conversions nécessaires
aussi bien lors de la lecture que lors de l’écriture.
D’une manière générale :
(cid:1) Si on souhaite dans une implémentation donnée, écrire des fichiers susceptibles d’être
lus par des logiciels manipulant des textes, ou encore lire des fichiers créés par de tels
logiciels. Dans ce cas, il est nécessaire d’utiliser des fichiers textes, afin d’assurer le
transcodage nécessaire entre code interne et code externe.
(cid:1) Si on est certain que les fichiers seront toujours manipulés par des programmes C
dans la même implémentation, dans ce cas, on peut se permettre d’utiliser des fichiers
binaires.
Il existe deux techniques d’accès aux fichiers:
(cid:1) Accès séquentiel: consiste à traiter les informations séquentiellement, càd dans l’ordre
où elles apparaissent dans le fichier, aussi bien en lecture qu’en écriture.
(cid:1) Accès direct: consiste à se placer immédiatement sur l’information souhaitée, sans
avoir à parcourir celles qui la précèdent.
Notion de flux
Dans bon nombre de langages, les fichiers ne se manipulent pas directement par leur « nom
externe », mais par un « nom interne » choisi librement par le programme. L’association du
nom externe au nom interne de fichier se fait au moment de l’ouverture par fopen.
Mme Wiem Yaiche Elleuch
les fichiers binaires
Page 1
Le nom interne est un pointeur sur une structure de type FILE (synonyme prédéfini par
typedef dans stdio.h).
Exemple :
FILE *fp ; // fp représente un flux
L’identificateur fp est un nom interne de fichier.
fp= fopen (« c:\\info.txt », « wb+ ») ; // fp est le nom interne du fichier info.txt
Cette instruction crée la correspondance entre nom externe et nom interne.
On parle de flux binaire ou de flux texte pour désigner un flux associé à un fichier ouvert en
mode binaire ou en mode texte.
La structure de type FILE ainsi associée au fichier comporte un certain nombre
d’informations, permettant d’assurer la bonne gestion du fichier tels que :
(cid:1) Un pointeur à l’intérieur du fichier
(cid:1) Un indicateur d’erreur
(cid:1) Un indicateur de fin de fichier
(cid:1) etc
En matière de traitement de fichiers en C, on distingue :
(cid:1) Le mode d’ouverture du fichier (binaire ou texte), ce qui amène à parler de flux
binaire ou de flux texte. Certaines implémentations ne font pas cette distinction.
(cid:1) Le type des opérations que l’on y effectue : binaires ou formatées, et ce
indépendamment du mode d’ouverture
(cid:1) Le type d’accès au fichier : séquentiel ou direct.
Les opérations relatives aux fichiers binaires
fwrite(&bloc, sizeof(bloc),n,fp);
Permet de transférer « n » blocs consécutifs de même taille « sizeof(bloc) » vers le
fichier « fp », à partir d’une adresse donnée de la mémoire «&bloc». (càd écrire sous forme
binaire des informations dans le fichier).
fwrite possède 4 arguments:
(cid:1) &bloc : Adresse en mémoire d’un bloc d’informations à partir de la quelle seront
copiées les informations à écrire dans le fichier.
(cid:1) sizeof(bloc) : La taille en octets d’un bloc
(cid:1) n : Le nombre de blocs de cette taille à transférer (à écrire) dans le fichier
(cid:1)
fp : Descripteur du fichier (nom du flux concerné): l’adresse de la structure de type
FILE décrivant le fichier.
La valeur de retour de fwrite correspond au nombre de blocs effectivement écrits dans le
fichier.
fwrite(&bloc, sizeof(bloc),n,fp);
Permet d’écrire n blocs, chacun de taille
sizeof (bloc).
fwrite(&bloc, n* sizeof(bloc),1,fp);
Permet d’écrire 1 bloc de taille
n*sizeof(bloc).
Ces deux instructions sont équivalentes. La différence apparaît en cas d’erreur d’écriture:
(cid:1) La première peut écrire dans le fichier les premiers blocs.
(cid:1) La deuxième : le bloc est écrit en totalité, ou bien n’est pas écrit.
Mme Wiem Yaiche Elleuch
les fichiers binaires
Page 2
fread (&bloc,sizeof(bloc),n, fp);
Permet de lire sous forme binaire (brute) à partir du fichier « fp », au maximum « n » blocs de
Publicité
taille « sizeof(bloc) » octets, et les range à partir de l’adresse « &bloc » dans la mémoire.
La fonction fread possède 4 arguments:
(cid:1) Adresse en mémoire à partir de la quelle seront rangées les informations lues à partir
du fichier.
(cid:1) La taille en octet de chaque bloc
(cid:1) Le nombre de blocs à lire
(cid:1) Descripteur du fichier
La valeur de retour de fread correspond au nombre de blocs effectivement lus à partir du
fichier.
fread (&bloc,sizeof(bloc),n, fp);
fread(&bloc, n* sizeof(bloc),1,fp);
Permet de lire n blocs, chacun de taille sizeof
(bloc).
Ces deux instructions sont équivalentes. La différence apparaît en cas d’erreur de lecture:
Permet de lire 1 bloc de taille n*sizeof(bloc).
(cid:1) La première peut lire les premiers blocs à partir du fichier.
(cid:1) La deuxième : le bloc est lu en totalité, ou bien n’est pas lu.
La fonction fclose
Réalise la fermeture du fichier.
Le « pointeur de fichier » indique l’emplacement auquel commencera la prochaine
opération de lecture ou d’écriture.
Un « pointeur de fichier » = « emplacement dans un fichier » : est un nombre qui précise le
rang du prochain octet à lire ou à écrire dans le fichier, il agit au niveau de l’octet.
En C, la notion d’enregistrement est quasi absente et l’accès direct peut se faire à un octet
quelconque de rang donné (voir plus loin la fonction fseek). Donc, il faut être en mesure de
calculer correctement le numéro de l’octet voulu.
Détection de la fin de fichier avec feof
La structure de type FILE associée à un fichier comporte un indicateur de fin de fichier qui
peut être examiné à l’aide de la fonction feof. La lecture des derniers octets d’un fichier ne
permettra pas d’en détecter la fin, il faudra tenter de lire au-delà, càd au moins un octet
inexistant.
feof prend la valeur vrai (non nul) lorsque la fin de fichier a été rencontrée. feof ne travaille
pas par anticipation, càd il n’est pas suffisant d’avoir lu le dernier octet du fichier pour que
cette condition prenne la valeur vrai. Il est nécessaire d’avoir tenté de lire au-delà. C’est
pourquoi il faut examiner cette condition après l’appel de fread et non avant.
La fonction fopen
fopen possède deux arguments :
(cid:1) Le nom du fichier concerné, fournit sous forme d’une chaîne de caractère. Il peut
également comporter une information (chemin, répertoire,..) permettant de préciser
l’endroit où se trouve le fichier.
Mme Wiem Yaiche Elleuch
les fichiers binaires
Page 3
char nom[30] ;
gets(nom) ;
fp= fopen (nom, « wb+ ») ;
ou bien
fp=fopen (« c:\\données\\essai.txt », « wb+ ») ;
(cid:1) Une indication fournie sous forme d’une chaîne de caractères, précisant ce que l’on
souhaite faire avec le fichier (r, w, rb, rw, etc).
La fonction fopen fournit en résultat un pointeur sur une structure FILE qu’elle a alloué
dynamiquement, lorsque l’opération d’ouverture a réussi. Dans le cas contraire, elle fournirait
un pointeur nul.
Les différentes possibilités d’ouverture d’un fichier
(cid:2) r: (read) lecture seulement. le fichier doit exister
(cid:2) w: (write) écriture seulement. si le fichier n’existe pas, il est créé. s’il existe, son
(ancien) contenu est perdu.
(cid:2) a: (append) écriture en fin de fichier. si le fichier existe déjà, il sera étendu. s’il
n’existe pas, il sera créé. on se ramène alors au mode w.
(cid:2) r+: mise à jour, (lecture et écriture). le fichier doit exister.
(cid:2) w+: création pour mise à jour. si le fichier existe, son ancien contenu sera détruit. s’il
n’existe pas, il sera créé.
(cid:2) a+: extension et mise à jour. si le fichier n’existe pas, il sera créé. s’il existe, le
pointeur sera positionné en fin de fichier.
(cid:2) t ou b, lorsque l’implémentation distingue les fichiers de texte des autres, il est
possible d’ajouter l’une de ces deux lettres à chacun des 6 modes précédents.
(cid:1)
t: fichier texte
(cid:1) b: fichier binaire
Exemple1 : remplir et afficher un fichier binaire d’entiers
#include<stdio.h>
void main()
{
char nomfich[21];
int n;
FILE *fp;
printf("saisir nom fichier ");
scanf("%s",nomfich);
fp=fopen(nomfich, "wb+");
do
{
printf("donner un entier; 0 pour s'arreter ");
scanf("%d",&n);
if (n!=0) fwrite (&n, sizeof(int),1,fp);
}
while(n!=0);
Mme Wiem Yaiche Elleuch
les fichiers binaires
Page 4
rewind (fp);
while ( !feof(fp))
{
fread(&n,sizeof(int),1,fp);
Publicité
if(!feof(fp)) printf("\n %d\n",n);
}
fclose (fp);
}
Ou bien
do
{
fread(&n,sizeof(int),1,fp);
if(!feof(fp)) printf("\n %d\n",n);
}
while (!feof(fp));
Même programme en utilisant les fonctions
#include<stdio.h>
#include<stdlib.h>
void ouverture (FILE **fp)
{
char nomfich[21];
printf("saisir nom fichier ");
scanf("%s",nomfich);
*fp=fopen(nomfich, "wb+");
if (!*fp) exit(-1);
}
void remplir_fichier (FILE *fp)
{
int n;
do
{
printf("donner un entier; 0 pour s'arreter ");
scanf("%d",&n);
if (n!=0) fwrite (&n, sizeof(int),1,fp);
}
while(n!=0);
}
void afficher_fichier (FILE *fp)
{
int n;
while ( !feof(fp))
{
fread(&n,sizeof(int),1,fp);
if(!feof(fp)) printf("\n %d\n",n);
}
}
Mme Wiem Yaiche Elleuch
les fichiers binaires
Page 5
void main()
{
FILE *fp;
ouverture (&fp);
remplir_fichier(fp);
rewind (fp);
afficher_fichier(fp);
fclose (fp);
}
Exemple 2 : remplir et afficher un fichier binaire d’etudiants : le nombre d’étudiants n’est pas
connu à l’avance. La condition d’arrêt est lorsque ce=-1.
#include<stdio.h>
#include<stdlib.h>
struct date
{
int jour;
int mois;
int annee;
};
typedef struct date DATE;
struct etudiant
{
int ce; // numéro carte d’étudiant
char nom[30];
float notes[5];
DATE date_naiss ;
};
typedef struct etudiant ETUDIANT;
/*/
void ouverture (FILE **fp)
{
char nf[20];
printf("saisir nom fichier");
gets(nf);
*fp=fopen(nf,"wb+");
}
/**/
void remplir_notes (float *t)
{
int i;
for (i=0; i<5; i++)
scanf("%f", t+i);
}
/**/
void afficher_notes (float *t)
{
int i;
for (i=0; i<5; i++)
Publicité
printf("%f", *(t+i));
}
Mme Wiem Yaiche Elleuch
les fichiers binaires
Page 6
/**/
int saisir_etudiant (ETUDIANT *e)
{
// condition d'arrêt: cin=-1
printf("\n saisir ce \n");
scanf("%d", &e->ce);
if(e->ce==-1) return 0;
printf("\n saisir nom ");
scanf("%s", e->nom);
printf("\n saisir les notes ");
remplir_notes(e->notes);
printf("\n saisir la date de naissance \n");
scanf("%d%d%d",&e->date_naiss.jour, &e->date_naiss.mois, &e->date_naiss.annee);
return 1;
}
/**/
void remplir_fichier(FILE *fp)
{
ETUDIANT etd;
while ( saisir_etudiant (&etd)) // ou bien while (saisir_employe(&emp) ==1)
fwrite(&etd, sizeof(ETUDIANT), 1,fp);
}
//
void remplir_fichier2 (FILE *fp)
ETUDIANT e;
{
while(1)
{
printf("\n saisir ce \n");
scanf("%d", &e.ce);
if(e.ce==-1) break;
printf("\n saisir nom ");
scanf("%s", e.nom);
printf("\n saisir les notes ");
remplir_notes(e.notes);
printf("\n saisir la date de naissance \n");
scanf("%d%d%d",&e.date_naiss.jour, &e.date_naiss.mois, &e.date_naiss.annee);
fwrite(&e, sizeof(ETUDIANT), 1,fp);
}
}
//
void affichage_fichier(FILE *fp)
{
ETUDIANT etd;
while(1)
{
fread(&etd,sizeof(ETUDIANT),1,fp);
if(feof(fp)) break;
printf("\n %4d %20s \n", etd.ce, etd.nom );
afficher_notes(etd.notes);
printf("\n %2d %2d %4d \n", etd.date_naiss.jour, etd.date_naiss.mois,
etd.date_naiss.annee);
}
}
Mme Wiem Yaiche Elleuch
les fichiers binaires
Page 7
/*/
void affichage_fichier2(FILE *fp)
{
ETUDIANT etd;
fread(&etd,sizeof(ETUDIANT),1,fp);
while(!feof(fp))
{
printf("\n %4d %20s \n", etd.ce, etd.nom );
afficher_notes(etd.notes);
printf("\n %2d %2d %4d \n", etd.date_naiss.jour, etd.date_naiss.mois, etd.date_naiss.annee);
fread(&etd,sizeof(ETUDIANT),1,fp);
}
}
/*/
void main()
{
FILE *fp;
ouverture (&fp);
remplir_fichier(fp); //ou bien remplir_fichier2(fp);
rewind(fp);
affichage_fichier(fp); // ou bien affichage_fichier2(fp) ;
fclose(fp);
}
/*/
La structure de type FILE associée à un fichier comporte un indicateur de fin de fichier qui
peut être examiné à l’aide de la fonction feof. Cet indicateur est extrêmement pratique pour
lire séquentiellement un fichier dont on ne connaît pas la taille.
feof(fp) : prend la valeur vrai (non nul) lorsque la fin du fichier a été rencontrée.
//
Après chaque opération de lecture ou d’écriture, le pointeur de fichier est incrémenté du
nombre d’octets transférés.
Publicité
Il est possible d’agir directement sur ce pointeur à l’aide de la fonction fseek. Ceci permet de
réaliser des lectures ou des écritures en n’importe quel point du fichier sans avoir besoin de
parcourir toutes les informations qui précèdent (accès direct).
fseek(fp, sizeof(int) * (pos-1), SEEK_SET);
OU BIEN
fseek(fp,sizeof(int) * (pos-1), 0);
=> Déplacement du pointeur de fichier de « sizeof(int) * (pos-1) » octets par rapport au
début du fichier (accès direct).
Cette fonction a trois arguments :
(cid:1) Le fichier concerné.
(cid:1) Un entier de type long spécifiant la valeur que l’on souhaite donner au pointeur de
fichier (déplacement).
(cid:1) Déplacement du pointeur de fichier à partir :
Mme Wiem Yaiche Elleuch
les fichiers binaires
Page 8
o Du début du fichier : SEEK_SET ou bien 0.
o De la position courante : SEEK_CUR ou bien 1 (le déplacement peut être
négatif).
o De la fin du fichier : SEEK_END ou bien 2.
Exemple :
…..
void afficher_etudiant (ETUDIANT etd)
{
printf("\n %4d %20s \n", etd.ce, etd.nom );
afficher_notes(etd.notes);
printf("\n %2d %2d %4d \n", etd.date_naiss.jour, etd.date_naiss.mois,
etd.date_naiss.annee);
}
/*/
void modifier_etudiant (ETUDIANT *e)
{
printf("\n saisir les nouvelles infos de l'etudiant \n");
printf("\n saisir ce \n");
scanf("%d", &e->ce);
printf("\n saisir nom ");
scanf("%s", e->nom);
printf("\n saisir les notes ");
remplir_notes(e->notes);
printf("\n saisir la date de naissance \n");
scanf("%d%d%d",&e->date_naiss.jour, &e->date_naiss.mois, &e->date_naiss.annee);
}
/*/
void main()
{
FILE *fp;
int pos;
long p;
ETUDIANT etd;
ouverture (&fp);
remplir_fichier(fp); //ou bien remplir_fichier2(fp);
rewind(fp);
printf("saisir la position de l'etudiant à modifier ");
scanf("%d",&pos);
fseek(fp, (pos-1) * sizeof(ETUDIANT), SEEK_SET);
p=ftell(fp);
fread(&etd,sizeof(ETUDIANT),1,fp);
afficher_etudiant(etd);
modifier_etudiant(&etd);
fseek(fp, p, SEEK_SET);
fwrite(&etd, sizeof(ETUDIANT), 1,fp);
Mme Wiem Yaiche Elleuch
les fichiers binaires
Page 9
fseek(fp, (pos-1) * sizeof(ETUDIANT), SEEK_SET);
fread(&etd,sizeof(ETUDIANT),1,fp);
afficher_etudiant(etd);
modifier_etudiant(&etd);
fseek(fp, -(long)sizeof(ETUDIANT), SEEK_CUR);
fwrite(&etd, sizeof(ETUDIANT), 1,fp);
rewind(fp);
affichage_fichier(fp); // ou bien affichage_fichier2(fp) ;
fclose(fp);
}
D’une manière générale :
long p ;
FILE *fp ;
p=ftell(fp) ; / pour mémoriser une position /
…
fseek(fp, p, SEEK_SET); / revenir à cette position plus tard /
ftell fournit la position courante du pointeur de fichier. On peut l’utiliser pour mémoriser une
position à la quelle on souhaite revenir ultérieurement.
Cette fonction peut donner la taille d’un fichier, et le nombre d’employés :
long taille ;
fseek(fp,0,SEEK_END) ;
taille = ftell(fp);
printf("la taille du fichier est %ld", taille);
printf("\n le nombre d'employés est %d", taille/sizeof(EMPLOYE));
rewind(fp) (cid:3)(cid:3)(cid:3)(cid:3) fseek(fp,0,0) ;
Mme Wiem Yaiche Elleuch
les fichiers binaires
Page 10