TP 8: LES FICHIERS en C
1. Types de Fichiers en C
Il y’a 2 types de fichiers en C:
· Les Fichiers Texte
· Les Fichiers Binaire
Fichiers Texte (ou ASCII American Standard Code for Information Interchange).
Avantages:
Fichiers qui peuvent être visualisés ,
Portables (déplaces et utilisés dans d’autres ordinateurs).
Inconvénients:
Nécessitent conversion pour être utilisés dans un PC donc moins performants.
Occupe plus d’espace qu’un fichier binaire
Fichiers Binaire: Contient même représentation que celle utilisée par la machine.
Avantages:
Occupe moins d’espace qu’un fichier text.
Plus rapide à lire ou à ecrire vu qu’aucune conversion n’est nécessaire.
Inconvénients:
Ces fichiers ne peuvent pas être visualisés.
Ne sont pas portables
Pour utiliser un fichier en C, il faut tout d'abord déclarer une variable de type FILE *.
FILE *<variableFichier>;
Exemple:
FILE *pFile;
2. Opérations sur les Fichiers (Texte et Binaire)
2.1 Ouverture de Fichier
FILE *fopen(const char *nomFichier, const char *mode) ;
Utilisation de fopen :
<variablefichier> = fopen(<nomFichier>, <mode>);
variablefichier : variable de type FILE *.
nomFichier : nom du fichier.
mode : mode d’ouverture du fichier
fopen retourne la valeur NULL en cas d’erreur.
nomFichier : nom du fichier.
Noter qu’on peut inclure le répertoire dans le nom du fichier.
Comme par exemple si le nom du fichier est "c:/putty/etud.txt" alors le fichier sera crée dans le repertoire putty dans le cas d’une création et est supposé existe dans le repertoire putty dans le cas d’une lecture.
Si le nom du fichier ne contient pas le répertoire comme par exemple "etud.txt", le fichier sera crée dans le même répertoire ou s’execute le programme dans le cas d’une création et le fichier est supposé existe dans le même répertoire ou s’execute le programme dans le cas d’une lecture.
ex: FILE *pFile;
pFile = fopen(“Donnees.txt”, “rt”);
Mode |
Signification du Mode |
Remarque |
r |
Ouverture en Lecture |
Si le fichier n’existe pas fopen() retourne NULL. |
w |
Ouverture en Ecriture |
Si le fichier existe son contenu est ecrasé. Si le fichier n’existe pas le fichier est crée. |
a |
Ouverture en Ajout. Les données sont ajoutés à la fin du fichier. |
Si le fichier n’existe pas le fichier est crée. |
r+ |
Ouverture en Lecture et en Ecriture (mise à jour) |
Si le fichier n’existe pas fopen() retourne NULL. |
w+ |
Ouverture en Lecture et en Ecriture |
Si le fichier existe son contenu est ecrasé. Si le fichier n’existe pas le fichier est crée. |
a+ |
Ouverture en Lecture et Ajout |
Si le fichier n’existe pas le fichier est crée. |
Remarque
A ces modes on ajoute "t" pour indiquer un fichier texte (par defaut) ou "b" pour indiquer un fichier binaire. Par exemple "rb" indique ouverture d'un fichier binaire en lecture.
2.2 Fermeture de Fichier
int fclose(FILE *pFile) ;
Ferme un fichier
2.3 Tester la Fin de Fichier (EOF: End Of
File)
int feof(FILE *pFile);
Cette fonction retourne une valeur différente de 0 si la fin de fichier (EOF) a été atteinte et qu'une tentative de lecture a été faite; sinon elle retourne la valeur 0.
Il faut faire attention à l'utilisation de cette fonction en C pour tester EOF car il faut faire une lecture après avoir atteint EOF pour que l'indicateur de fin de fichier soit mis à Vrai (c'est à dire que feof() retourne une valeur differente de 0 lorsque la fin de fichier a été atteinte et que une tentative de leture a été faite; sinon feof() retourne 0).
2.4 Opérations sur les Fichiers Texte
2.4.1 Opérations d’Ecriture
Fonction Action
fprintf() Ecriture formate dans un fichier:
int fprintf(FILE *stream,const char *format[, argument, ... J);
fputc() Ecriture d’un caractère dans un fichier
int fputc(int c, FILE *stream);
fputs() Ecriture d’une chaine de caractères dans un fichier
int fputs(const char *s, FILE *stream);
2.4.2 Operations de Lecture
Fonction Action
fscanf() Lecture formatée à partir d’un fichier
int fscanf(FILE *stream, const char *format[, address, ... J);
fgetc() Lecture d’un caractère d’un fichier
int fgetc(FILE *stream);
fgets() Lecture d’une chaine de caractères d’un fichier
char *fgets(char *s, int n, FILE *stream);
fgets lit les caractères de stream dans la chaine s. Cette fonction arrête la lecture lorsqu’elle lit (n – 1) caractères ou lorsqu’elle rencontre le caractère newline (nouvelle ligne). fgets ne met pas le caractère newline dans s. Le dernier caractère est suivi du caractère nul (fin de chaine de caractère).
En cas de succés la fonction retourne le même paramètre s. Si la fin de fichier est rencontré et aucun caractère n’est lu le contenu de s reste inchangé et le pointeur NULL est retourné.
En cas d’erreur le pointeur NULL est retourné.
Application
Creation et Lecture d’un fichier Texte d’etudiants. Le premier programme crée le fichier etud.txt et le deuxième programme lit le fichier etud.txt. Le fichier etud.txt est crée avec les informations de chaque etudiant sur une ligne du fichier.
Programme de creation du fichier Texte etudiant
#include <stdio.h>
#include <stdlib.h>
#define FichierIn "etud.txt"
#define nbrChars 100
typedef struct
{
long mat;
char nom[11];
char prenom[11];
float moyenne;
} etudiant;
int creerFichierTexteEtudiants(char nomFichier[]);
int main()
{
int ret;
ret = creerFichierTexteEtudiants(FichierIn);
if (ret == -1)
{
printf("Problems creating file etudiants ...\n");
system("pause");
return 1;
}
system("pause");
return 0;
}
int creerFichierTexteEtudiants(char nomFichier[])
{
FILE *pFile;
etudiant etd;
char buff[nbrChars];
int i, N;
pFile = fopen(nomFichier, "wt");
if (pFile == NULL)
{
printf("Erreur Pb avec Fichier %s Exiting ...", nomFichier);
return -1;
}
printf("Entrer Nombre Etudiants a Creer dans le Fichier\n");
scanf("%d", &N);
for (i=0; i < N; i++)
{
printf("Entrer Donnees etudiants matricule , nom, prenom et moyenne\n");
scanf("%ld %s %s %f", &etd.mat, etd.nom, etd.prenom, &etd.moyenne);
sprintf(buff, "%-5ld %-10s %-10s %5.2f\n", etd.mat, etd.nom, etd.prenom, etd.moyenne);
fputs(buff, pFile);
}
fclose(pFile);
return 1;
}
Programme de Lecture du fichier Texte etudiant
#include <stdio.h>
#include <stdlib.h>
#define FichierIn "etud.txt"
#define nbrChars 100
typedef struct
{
long mat;
char nom[11];
char prenom[11];
float moyenne;
} etudiant;
int lireFichierEtudiants(char nomFichier[]);
int main()
{
int ret;
ret = lireFichierEtudiants(FichierIn);
if (ret == -1)
{
printf("Problems reading file etudiants ...\n");
system("pause");
return 1;
}
system("pause");
return 0;
}
int lireFichierEtudiants(char nomFichier[])
{
char buff[nbrChars];
FILE *pFile;
etudiant etd;
pFile = fopen(nomFichier, "rt");
if (pFile == NULL)
{
printf("Erreur Pb avec Fichier %s Exiting ...", nomFichier);
system("pause");
return -1;
}
while ( (fgets(buff, nbrChars, pFile) != NULL) )
{
sscanf(buff, "%ld %s %s %f", &etd.mat, etd.nom, etd.prenom, &etd.moyenne);
printf("matricule = %ld , nom = %s, prenom = %s, moyenne = %f ****\n", etd.mat, etd.nom, etd.prenom, etd.moyenne );
}
fclose(pFile);
return 0;
}
Se Referer à 2.8 pour différences entre printf/fprintf/sprintf et scanf/fscanf/sscanf.
2.5 Opérations sur les Fichiers Binaires
2.5.1 Operateur sizeof()
sizeof(<var>) ou sizeof(<type>)
Retourne le nombre d’octets occupé par la variable ou le type
Exemple:
int x, sz;
sz = sizeof(x); /* sz = 4 sous dev-c++ */
ou bien
sz = sizeof(int); /* sz = 4 sous dev-c++ */
2.5.2 Opérations de Lecture
Fonction Action
fread() Lecture non formate d’un fichier
size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
fread lit n éléments de données, ou chaque élément a comme taille size octets, à partir de stream , et met les données lus en memoire à partir de l’adresse contenu dans le pointeur ptr. Le nombre total d’octets lus est (n x size).
fread retourne le nombre d’éléments lus avec succés. Si ce nombre est different de n alors ou bien il y’a eu erreur ou bien la fin de fichier a éte atteint.
2.5.3 Operations d’Ecriture
Fonction Action
fwrite() Ecriture non formaté dans un fichier
size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);
fwrite ajoute n éléments de données où chaque élément a size octets, au fichier stream . Les données ecrits démarrent de l’addresse ptr. Le nomber total d’octets ecrits est (n x size). ptr est un pointeur qui peut pointer vers n’importe quel objet (void *).
fwrite retourne le nombre d’éléments ecrits avec succés. Si ce nombre est différent de n alors il y’a eu erreur.
Applications
1) Creation et Lecture d’un fichier Binaire d’etudiants. Le premier programme crée le fichier binaire etud et le deuxieme programme lit le fichier binaire etud.dat.
Programme de creation du fichier binaire etudiant
#include <stdio.h>
#include <stdlib.h>
#define FichierIn "etud.dat"
typedef struct
{
long mat;
char nom[11];
char prenom[11];
float moyenne;
} etudiant;
int creerFichierBinEtudiants(char nomFichier[]);
int main()
{
int ret;
ret = creerFichierBinEtudiants(FichierIn);
if (ret == -1)
{
printf("Problems creating file etudiants ...\n");
system("pause");
return 1;
}
system("pause");
return 0;
}
int creerFichierBinEtudiants(char nomFichier[])
{
FILE *pFile;
etudiant etd;
int i, N;
pFile = fopen(nomFichier, "wb");
if (pFile == NULL)
{
printf("Erreur Pb avec Fichier %s Exiting ...", nomFichier);
return -1;
}
printf("Entrer
Nombre Etudiants a Creer Initialement dans le Fichier\n");
scanf("%d", &N);
for (i=0; i < N; i++)
{
printf("Entrer Donnees etudiants matricule , nom, prenom et moyenne\n");
scanf("%ld %s %s %f", &etd.mat, &etd.nom, &etd.prenom, &etd.moyenne);
fwrite(&etd, sizeof(etd), 1, pFile);
}
fclose(pFile);
return 1;
}
Programme de Lecture du fichier Binaire etudiant
#include <stdio.h>
#include <stdlib.h>
#define FichierIn "etud.dat"
typedef struct
{
long mat;
char nom[11];
char prenom[11];
float moyenne;
} etudiant;
int lireFichierBinEtudiants(char nomFichier[]);
int main()
{
int ret;
ret = lireFichierBinEtudiants(FichierIn);
if (ret == -1)
{
printf("Problems reading file etudiants ...\n");
system("pause");
return 1;
}
system("pause");
return 0;
}
int lireFichierBinEtudiants(char nomFichier[])
{
FILE *pFile;
etudiant etd;
pFile = fopen(nomFichier, "rb");
if (pFile == NULL)
{
printf("Erreur Pb avec Fichier %s Exiting ...", nomFichier);
return -1;
}
printf("Liste des Etudiants ...\n");
while (fread(&etd, sizeof(etd), 1, pFile) != 0)
{
printf("%-5ld %-10s %-10s %5.2f\n", etd.mat, etd.nom, etd.prenom, etd.moyenne);
}
fclose(pFile);
return 1;
}
2) Creation d’un fichier Binaire d’etudiants à partir d'un fichier texte et Lecture du fichier Binaire.
Il faudra d'abord créer le fichier texte etudiant "etd.txt" en utilisant un editeur de texte par exemple notepad (block note). Le fichier etd.txt doit se trouver dans le même répertoire où le projet de Codeblocks a été crée (où se trouve le main.c) et doit contenir une ligne par etudiant (une ligne d'un etudiant doit contenir le matricule, le nom, le prenom et la moyenne separés par un ou plusieurs blancs par exemple "110 benali Omar 12.5");
Programme de Création d'un Fichier Binaire à partir d'un Fichier Texte
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
long mat;
char nom[11];
char prenom[11];
float moyenne;
} etudiant;
int lireFichTxtCreeFichBin(char nomFTxt[], char nomFBin[])
{
char buff[100];
FILE *pFile1, *pFile2;
etudiant etd;
pFile1 = fopen(nomFTxt, "rt");
if (pFile1 == NULL)
{
printf("Erreur Pb avec Fichier %s Exiting ...\n", nomFTxt);
return -1;
}
pFile2 = fopen(nomFBin, "wb");
if (pFile2 == NULL)
{
printf("Erreur Pb avec Fichier %s Exiting ...\n", nomFBin);
return -1;
}
while ( (fgets(buff, 100, pFile1) != NULL) )
{
sscanf(buff, "%ld %s %s %f", &etd.mat, etd.nom, etd.prenom, &etd.moyenne);
fwrite(&etd, sizeof(etd), 1, pFile2);
}
fclose(pFile1);
fclose(pFile2);
return 0;
}
int lireFichierBinEtudiants(char nomFBin[])
{
FILE *pFile;
etudiant etd;
pFile = fopen(nomFBin, "rb");
if (pFile == NULL)
{
printf("Erreur Pb avec Fichier %s Exiting ...", nomFBin);
return -1;
}
printf("Fichier Binaire %s Liste des Etudiants ...\n", nomFBin);
while (fread(&etd, sizeof(etd), 1, pFile) != 0)
{
printf("%-5ld %-10s %-10s %5.2f\n", etd.mat, etd.nom, etd.prenom, etd.moyenne);
}
fclose(pFile);
return 1;
}
int main()
{
if (lireFichTxtCreeFichBin("etd.txt", "etd.bin") == - 1)
{
printf("Probleme avec Creation Fichier Binaire ...\n");
return 0;
}
if (lireFichierBinEtudiants("etd.bin") == -1)
{
printf("Probleme avec Lecture Fichier Binaire ...\n");
}
return 0;
}
2.6 Comment Tester l'existence d'un fichier en C
La fonction access() qui fait partie de "unistd.h" permet de tester si un fichier existe ou non.
Cette fonction doit être appelée comme: access(nomPhysiqueFichier, F_OK)
La fonction access retourne 0 dans le cas où le fichier existe.
Exemple:
Le code ici-bas ouvre le fichier "etd.dat" en écriture pour le créer si le fichier n'existe pas (dans le répertoire où il y'a le main.c) :
#include <unistd.h>
...
if (access("etd.dat", F_OK) != 0)
{
// Ouvrir le fichier etd.dat en ecriture et le creer si le fichier n'existe pas
FILE *pFile = fopen("etd.dat", "wb");
...
}
2.7 Opérations sur les pointeurs de fichier
Ces opérations s'appliquent aux fichiers binaires ainsi qu'aux fichiers textes.
fseek() Met position du pointeur de fichier à une position donnée dans le fichier.
int fseek(FILE *stream, long int offset, int whence);
fseek met pointeur de fichier à une position donnée dans le fichier associé à stream. Cette position est un offset (en octets) à partir de la position du fichier determiné par whence.
'whence doit avoir une de ces valeurs: 0, 1, 2.
SEEK_SET (0) : Debut du fichier
SEEK_CUR (1) : Position courante dans le fichier
SEEK_END (2) : Fin de fichier
Apres fseek, la prochaine opération peut être soit une lecture soit une écriture.. fseek retourne 0 si le pointeur est deplacé avec succés et retourne une valeur différente de zero en cas d’echec.
D'autres opérations sont disponibles en C: fgetpos(), ftell() ainsi que fsetpos().
rewind() Met la position du pointeur de fichier au début du fichier.
rewind(stream) est équivalente à fseek(stream, O, SEEK_SET),
Remarque Importante
Pour les fichiers qui sont ouvert en mode mise a jour (“r+b”, “w+b”, “a+b” pour les fichiers binaires) les 2 conditions suivantes s’appliquent:
Si une opération de lecture (fread) suit une operation d’ecriture (fwrite) le fichier devra être flushé (avec fflush) ou bien repositionné (avec fseek ou bien fsetpos) entre les 2 opérations.
Si une opération d’ecriture (fwrite) suit une opération de lecture (fread) le fichier devra être repositionné (avec fseek ou bien fsetpos) entre les 2 opérations sauf dans le cas ou l’opération de lecture (fread) a rencontré la fin du fichier.
Si une de ces 2 conditions n'est pas respectée, le resultat est imprévisible.
La fonction fflush() est utilisé pour vider le tampon (buffer) et écrire sur le disque (pour fichier situé sur disque)..
Application
Programme qui crée un fichier binaire d’etudiants ensuite qui offre un menu pour afficher la liste des étudiants, ajouter un étudiant au fichier ou modifier la moyenne d’un étudiant.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define FichierBinIn "etudiant.dat"
typedef struct
{
int mat;
char nom[11];
char prenom[11];
float moyenne;
} etudiant;
int creerBinFichierEtudiants(char []);
int lireBinFichierEtudiants(char []);
int modifierBinFichierEtudiants(char nomFichier[]);
int ajouterBinUnEtudiantAlaFin(char nomFichier[]);
int main()
{
int choix;
if (access(FichierBinIn, F_OK) != 0) // creer Fichier FichierBinIn si n'a pas deja ete cree
{
if (creerBinFichierEtudiants(FichierBinIn) == -1)
{
printf("Problems creerBinFichierEtudiants ...\n");
system("pause");
return 1;
}
}
if (lireBinFichierEtudiants(FichierBinIn) == -1)
{
printf("Problems lireBinFichierEtud ...\n");
system("pause");
return 1;
}
while (1)
{
printf("Menu Choix : \n");
printf("1: ajouter un etudiant ...\n");
printf("2: modifier moyenne un etudiant ...\n");
printf("3: afficher liste des etudiants ...\n");
printf("0: quitter le programme ...\n");
scanf("%d", &choix);
if (choix == 0)
break;
switch(choix)
{
case 1:
if (ajouterBinUnEtudiantAlaFin(FichierBinIn) == -1)
{
printf("Problems ajouter un etudiant au Fichier %s ...\n", FichierBinIn);
system("pause");
return 1;
}
break;
case 2:
if (modifierBinFichierEtudiants(FichierBinIn) == -1)
{
printf("Problems modifierBinFichierEtud ...\n");
system("pause");
return 1;
}
break;
case 3:
if (lireBinFichierEtudiants(FichierBinIn) == -1)
{
printf("Problems lire Fichier %s ...\n", FichierBinIn);
system("pause");
return 1;
}
break;
}
}
system("pause");
return 0;
}
int creerBinFichierEtudiants(char nomFichier[])
{
FILE *pFile;
etudiant etd;
int i, nbr;
pFile = fopen(nomFichier, "wb");
if (pFile == NULL)
{
return -1;
}
printf("Donner Combien d'Enregistrements vous voulez creer ...\n");
scanf("%d", &nbr);
for (i=0; i < nbr; i++)
{
printf("Entrer Donnees etudiants matricule , nom, prenom et moyenne\n");
scanf("%d %s %s %f", &etd.mat, etd.nom, etd.prenom, &etd.moyenne);
fwrite(&etd, sizeof(etd), 1, pFile);
}
fclose(pFile);
return 1;
}
int lireBinFichierEtudiants(char nomFichier[])
{
FILE *pFile;
etudiant etd;
pFile = fopen(nomFichier, "rb");
if (pFile == NULL)
{
return -1;
}
printf("Liste des Etudiants ...\n");
while (fread(&etd, sizeof(etd), 1, pFile) != 0)
{
printf("%-5d %-10s %-10s %5.2f\n", etd.mat,
etd.nom, etd.prenom, etd.moyenne);
}
printf("\n");
fclose(pFile);
return 1;
}
int ajouterBinUnEtudiantAlaFin(char nomFichier[])
{
FILE *pFile;
etudiant etd;
pFile = fopen(nomFichier, "ab");
if (pFile == NULL)
{
printf("Erreur Pb avec Fichier %s Exiting ...", nomFichier);
return -1;
}
printf("Entrer Donnees etudiants matricule , nom, prenom et moyenne\n");
scanf("%d %s %s %f", &etd.mat, etd.nom, etd.prenom, &etd.moyenne);
fwrite(&etd, sizeof(etd), 1, pFile);
fclose(pFile);
return 1;
}
int modifierBinFichierEtudiants(char nomFichier[])
{
FILE *pFile;
etudiant etd;
int mat;
pFile = fopen(nomFichier, "rb+");
if (pFile == NULL)
{
return -1;
}
printf("Donner Matricule Etudiant a Modifier ...\n");
scanf("%d", &mat);
while (fread(&etd, sizeof(etd), 1, pFile) != 0)
{
if (etd.mat == mat)
break;
}
if (etd.mat != mat)
{
printf("Erreur: Matricule %d N'Existe Pas dans le fichier %s\n", mat, nomFichier);
return 1;
}
printf("Veuillez entrer Nouvelle moyenne de etudiant %s %s ...\n", etd.nom, etd.prenom);
scanf("%f", &etd.moyenne);
fseek(pFile, -1 * sizeof(etudiant), SEEK_CUR);
fwrite(&etd, sizeof(etd), 1, pFile);
fclose(pFile);
return 1;
}
2.8 Differences entre printf/fprintf/sprintf et scanf/fscanf/sscanf
printf - Est utilisée pour afficher sur écran (ou sur imprimante)
sprintf - est utilisée pour sauvegarder une suite de caractères codés en ascii dans un buffer (tampon) de caractères. Un buffer est un vecteur de char.
fprintf - est utilisée pour sauvegarder une chaine de caractères codée en ascii dans un fichier texte.
printf Exemple
#include <stdio.h>
int main()
{
printf("Bonjour Tout Le Monde!\n");
return 0;
}
sprintf Exemple
#include <stdio.h>
int main()
{
char buffer[50];
int a = 10, b = 20, c;
c = a + b;
sprintf(buffer, "Somme de %d a et %d est %d", a, b, c);
// La chaine "Somme de 10 et 20 est 30" est sauvegardee
// dans buffer au lieu d'etre affiche sur ecran
printf("%s", buffer);
return 0;
}
fprimtf Exemple
#include <stdio.h>
int main()
{
int i, n=5;
char str[50];
//ouvrir sample.txt en mode ecriture
FILE *fptr = fopen("sample1.txt", "wt");
if (fptr == NULL)
{
printf("Ne peut pas ouvrir Fichier sample1.txt");
return 0;
}
for (i=0; i<n; i++)
{
printf("Donner un nom:");
scanf("%s", str);
fprintf(fptr,"%d.%s\n", i, str);
}
fclose(fptr);
return 0;
}
scanf - fscanf - sscanf
scanf: Lit à partir du clavier(stdin)
fscanf: Lit à partir d'un fichier
sscanf: Lit à partir d'un buffer
scanf Exemple
#include <stdio.h>
#include <stdlib.h>
int main()
{
char nom[30];
int age;
printf("Donner Nom :");
scanf("%s", nom);
printf("Donner Age :");
scanf("%d", &age);
printf("Vous aviez donne: \nNom:%s et Age:%d", nom, age);
return 0;
}
sscanf Exemple
#include <stdio.h>
int main ()
{
// declaring array s
char s[] = "112 Benali Omar";
int mat;
char nom[30],prenom [30];
sscanf (s,"%d %s %s", &mat, nom, prenom);
printf ("%d %s %s \n", mat, nom, prenom);
return 0;
}
fscanf Exemple
#include <stdio.h>
int main ()
{
int mat;
char nom[30],prenom [30];
//ouvrir sample.txt en mode lecture
FILE *fptr = fopen("sample2.txt", "rt");
if (fptr == NULL)
{
printf("Ne peut pas ouvrir Fichier sample2.txt en lecture");
return 0;
}
fscanf (fptr,"%d %s %s", &mat, nom, prenom);
printf ("%d %s %s \n", mat, nom, prenom);
fclose(fptr);
return 0;
}