pdf - e-book - archive - github.com

1.11  Fichiers

1.11.1  Définitions

Supposons que l’on dispose d’un programme permettant saisir 10 entiers dans un tableau.

#include<stdio.h>

int main()
{
  int t[10], i;
  for(i = 0; i < 10 ; i++)
    {
      printf("Saisir un entier : ");
      scanf("%d", t + i);
    }
  for(i = 0 ; i < 10 ; i++)
    printf("%d ", t[i]);
  printf("\n");
  return 0;
}

Télécharger le fichier

Le problème qui se pose est que lorsque l’on sort de ce programme, les données saisies sont perdues. Si l’on souhaite les avoir à disposition pour d’une exécution ultérieure, il convient d’utiler une mémoire persistante, c’est-à-dire qui conserve les données entre deux exécutions. On utilise pour ce faire un fichier. Un fichier est une mémoire stockée de façon permanente sur un disque et à laquelle on accède avec un nom. Les données dans un fichier se présentent de façon séquentielle, et donc se lisent ou s’écrivent du début vers la fin.

Nous survolerons dans ce cours un ensemble de fonctions de stdio.h permettant de manier des fichiers. Pour plus détails, il est très hautement recommandé de se reporter à la documentation.

1.11.2  Ouverture et fermeture

Pour accéder au contenu d’un fichier en lecture ou en écriture, on utilise les deux fonctions fopen et fclose.

La fonction fopen

fopen permet, comme son nom l’indique, d’ouvrir un fichier. Son prototype est FILE *fopen(const char *path, const char *mode) :

La fonction fclose

fclose sert à fermer un fichier. Son prototype est int fclose(FILE *fp) :

Utilisation

Si l’on souhaite par exemple lire dans un fichier s’appelant "toto.txt" :

#include<stdio.h>

int main()
{
  FILE* f;
  f = fopen("toto.txt", "r");
  if (f == NULL)
    {
      printf("Erreur lors de l'ouverture du fichier toto.txt\n");
      return -1;
    }
  /*
    Lecture dans le fichier
    ...
   */
  if (fclose(f))
    {
      printf("Erreur lors de la fermeture du fichier toto.txt\n");
      return -1;
    }
  return 0;
}

Télécharger le fichier

1.11.3  Lecture et écriture

Il existe plusieurs façons de lire dans un fichier : caractère par caractère, ligne par ligne, par paquets de caractères, etc. Chaque lecture se faisant à l’aide d’une fonction appropriée. Lors d’un traitement se faisant à partir d’une lecture dans un fichier, on appelle de façon itérée une fonction de lecture faisant avancer un curseur dans un fichier jusqu’à ce que la fin du fichier soit atteinte.

L’écriture fonctionne de façon analogue, à un détail près : il est inutile d’écrire le caractère de fin de fichier, il est ajouté automatiquement lors du fclose.

Caractère par caractère

La fonction int fgetc(FILE* stream) retourne un caractère lu dans le fichier f. Bien que le caractère lu soit un octet, il est retourné dans un int. Le caractère EOF indique que la fin du fichier a été atteinte. Par exemple,

#include<stdio.h>

int main()
{
  FILE* f;
  char c;
  f = fopen("toto.txt", "r");
  if (f == NULL)
    {
      printf("Erreur lors de l'ouverture du fichier toto.txt\n");
      return -1;
    }
  while((c = fgetc(f)) != EOF)
    printf("caractere lu : %c\n", c);
  if (fclose(f))
    {
      printf("Erreur lors de la fermeture du fichier toto.txt\n");
      return -1;
    }
  return 0;
}

Télécharger le fichier

On écrit un caractère dans un fichier à l’aide de la fonction int fputc(int c, FILE* stream).

#include<stdio.h>

int main()
{
  FILE* f;
  char c[8] = "Toto !\n";
  int i;
  f = fopen("toto.txt", "w");
  if (f == NULL)
    {
      printf("Erreur lors de l'ouverture du fichier toto.txt\n");
      return -1;
    }
  for(i = 0 ; i < 7 ; i++)
    fputc(c[i], f);
  if (fclose(f))
    {
      printf("Erreur lors de la fermeture du fichier toto.txt\n");
      return -2;
    }
  return 0;
}

Télécharger le fichier

Par chaînes de caractères

Les deux fonctions char *fgets(char *s, int size, FILE *stream) et int fputs(const char *s, FILE *stream) permettent de lire et d’écrire des chaînes de caractères dans des fichiers, voir la documentation pour plus de détails.

Par paquets

Les deux fonctions size\_t fread(void *ptr, size\_t size, size\_t nmemb, FILE *stream) et size\_t fwrite(const void *ptr, size\_t size, size\_t nmemb, FILE *stream) sont très utiles lorsque l’on veut sauvegarder un tableau dans un fichier, ou recopier un fichier dans un tableau (voir la documentation pour plus de détails). Voici tout de même deux exemples :

#include<string.h>
#include<stdio.h>

struct personne
{
  char nom[30];
  int age;
};

int main(int argv, char** argc)
{
 FILE* f;
 struct personne repertoire[4] = 
   {{"tata", 2}, {"toto", 8}, {"titi", -1}, {"tutu", 9}}; 
 f = fopen("toto.txt", "w");
 if (f == NULL)
   {
     printf("Impossible d'ouvrir le fichier toto.txt");
     return -1;
   }
 fwrite(repertoire, 4, sizeof(struct personne), f);
 if (fclose(f))
   {
     printf("Impossible de fermer le fichier toto.txt");
     return -2;
   }
 return 0;
}

Télécharger le fichier

#include<string.h>
#include<stdio.h>

struct personne
{
  char nom[30];
  int age;
};

int main(int argv, char** argc)
{
 FILE* f;
 int i, n = 0;
 struct personne repertoire[4];
 f = fopen("toto.txt", "r");
 if (f == NULL)
   {
     printf("Impossible d'ouvrir le fichier toto.txt.\n");
     return -1;
   }
 while(fread(repertoire + n, 1, sizeof(struct personne), f))
   n++;
 for (i = 0 ; i < n ; i++)
   printf("%s %d\n", repertoire[i].nom, repertoire[i].age);
 if (fclose(f))
   {
     printf("Impossible de fermer le fichier toto.txt.\n");
     return -2;
   }
 return 0;
}

Télécharger le fichier