Entrées/Sorties sur un fichier texte









NB, les entrées/sorties sur un fichier binaire ne seront pas traitées dans le cadre de la mise à niveau. Rappelons qu'un fichier texte est un fichier qui est lisible, il peut être édité dans votre éditeur de texte.
Lorsque vous voulez obtenir des informations sur le fichier, vous pouvez utiliser la commande file, pour un fichier exécutable vous obtiendrez executable, un fichier binaire data et un fichier texte text
> file donnees.bin
donnees.bin: data
> file donnees.txt
donnees.txt: ASCII text
> file lignes
lignes: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), 
dynamically linked (uses shared libs), not stripped
>

Ouverture d'un fichier

La fonction FILE *fopen(char *nomfic, char *mode) ouvre le fichier dont le nom est donné comme premier argument, selon le mode d'ouverture précisé (w = écriture, r = lecture, a = ajout en fin de fichier) et l'assigne à un flux, i.e. à une variable de type FILE *.
Dans le programme ci-dessous, nom_fic est une chaîne de caractères qui contient le nom du fichier à ouvrir, et fic est une variable de type FILE *.
  // ouverture du fichier
  fic = fopen(nom_fic, "r"); // ouvrir en lecture
  if(fic == NULL){
      printf("Impossible d'ouvrir le fichier %s\n", nom_fic);
      exit(1);
  }
  printf(".............. Ouverture du fichier %s\n", nom_fic);

Fermeture d'un fichier

  // fermeture du fichier
  if(fclose(fic) == EOF){
      printf("Probleme de fermeture du fichier %s", nom_fic);
      exit(1);
  }
  printf(".............. Fermeture du fichier %s\n", nom_fic);

Lecture des données d'un fichier

fgets

La fonction char *fgets(char *chaine, int max, FILE *fichier) lit une chaîne de caractères sur le fluxfichier et la stocke dans la chaîne chaine. Elle lit au maximum max - 1 caractères, elle s'arrête dès qu'elle rencontre un caractère de passage à la ligne et place un \0 à la fin de la chaîne. Lorsqu'elle rencontre la fin de fichier, elle retourne la chaîne NULL.
Prenons un programme qui affiche le contenu d'un fichier et compte le nombre de lignes de ce fichier :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void verif_et_recup_arg(int nb, char *arguments[], int nb_souhaite, char *chaine)
{
  if(nb != nb_souhaite){
    printf("Usage : lignes nom_fichier\n");
    exit(1);
  }

  strcpy(chaine, arguments[1]);
}

int main(int argc, char *argv[]) {
  FILE *fic; 
  int nb_lignes;
  char ligne_lue[512];
  char nom_fic[255];

  verif_et_recup_arg(argc, argv, 2, nom_fic);
  
  // ouverture du fichier
  fic = fopen(nom_fic, "r"); // ouvrir en lecture
  if(fic == NULL){
      printf("Impossible d'ouvrir le fichier %s\n", nom_fic);
      exit(1);
  }
  printf(".............. Ouverture du fichier %s\n", nom_fic);

  // compter et afficher les lignes du fichier
  nb_lignes = 0;
  while(fgets(ligne_lue, 512, fic) != NULL){
    printf("\t%s", ligne_lue);
    nb_lignes++;
  }
  printf("le fichier %s comporte %d lignes\n", nom_fic, nb_lignes);

  // fermeture du fichier
  if(fclose(fic) == EOF) {
      printf("Probleme de fermeture du fichier %s", nom_fic);
      exit(1);
  }
  printf(".............. Fermeture du fichier %s\n", nom_fic);

  return 0;
}
NB : le \n n'est pas placé dans le printf("\t%s", ligne_lue); qui affiche le contenu de la variable ligne_luecar fgets stocke le caractère de retour à la ligne quand il le lit. Si nous avions demandé printf("\t%s\n", ligne_lue);. Nous aurions obtenu sur la console une ligne blanche entre chaque ligne du fichier.
> ls
donnees.txt  lignes.c
> more donnees.txt
une chaine sur la 1ere ligne
une autre chaine sur la 2eme ligne
14
3.5
une chaine sur la 5eme ligne
derniere ligne avant la fin
> gcc -Wall lignes.c -o lignes
> ./lignes
Usage : lignes nom_fichier
> ./lignes donnee.txt
Impossible d'ouvrir le fichier donnee.txt
> ./lignes donnees.txt
.............. Ouverture du fichier donnees.txt
        une chaine sur la 1ere ligne
        une autre chaine sur la 2eme ligne
        14
        3.5
        une chaine sur la 5eme ligne
        derniere ligne avant la finle fichier donnees.txt comporte 6 lignes
.............. Fermeture du fichier donnees.txt
>
Nous avons précisé que fgets lit au maximum le nombre de caractères - 1 précisé en argument. Lorsqu'on souhaite lire une ligne entière, on donne un maximum élevé. Si dans notre exemple, nous avions écrit : fgets(ligne_lue, 10,fic) à la place de fgets(ligne_lue, 512, fic), nous aurions obtenu le résultat ci-dessous :
> ./lignes donnees.txt
.............. Ouverture du fichier donnees.txt
        une chain       e sur la        1ere lign       e
        une autre        chaine s       ur la 2em       e ligne
        14
        3.5
        une chain       e sur la        5eme lign       e
        derniere        ligne ava       nt la finle fichier donnees.txt comporte 17 lignes
.............. Fermeture du fichier donnees.txt
>

fscanf

La fonction fscanf(FILE *fichier, char *format, adr_var_1, adr_var_2, ...) prend comme premier argument le flux dans lequel elle doit lire et stocke les données lues selon le format défini par la chaîne format dans les variables adr_var_ passées par adresse.
Le programme ci-dessous utilise la fonction scanf pour stocker dans des variables les informations d'un fichier annuaire qui comporte sur chaque ligne un nom, un prénom, le numéro de téléphone et l'adresse mail d'une personne. NB : on suppose que le nom de la personne ne comporte pas d'espace.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void verif_et_recup_arg(int nb, char *arguments[], int nb_souhaite, char *chaine)
{
  if(nb != nb_souhaite){
    printf("Usage : annuaire nom_fichier\n");
    exit(1);
  }

  strcpy(chaine, arguments[1]);
}

int main(int argc, char *argv[])
{
  FILE *fic; 
  int nb_lignes, t1, t2, t3, t4, t5;
  char nom_fic[255], nom[255], prenom[255], mail[255];

  verif_et_recup_arg(argc, argv, 2, nom_fic);
  
  // ouverture du fichier
  fic = fopen(nom_fic, "r"); // ouvrir en lecture
  if(fic == NULL){
      printf("Impossible d'ouvrir le fichier %s\n", nom_fic);
      exit(1);
  }
  printf(".............. Ouverture du fichier %s\n\n", nom_fic);

  // recuperer les donnees de l'annuaire
  nb_lignes = 0;
  while(fscanf(fic, "%s %s %d %d %d %d %d %s", nom, prenom,\
               &t1, &t2, &t3, &t4, &t5, mail) != EOF){
    printf("\tnom = %s\n \tprenom = %s\n \ttel = %.2d %.2d %.2d %.2d %.2d\n \tmail = %s\n\n",\
        nom, prenom, t1, t2, t3, t4, t5, mail);
    nb_lignes++;
  }
  printf("le fichier %s comporte %d lignes\n", nom_fic, nb_lignes);

  // fermeture du fichier
  if(fclose(fic) == EOF){
      printf("Probleme de fermeture du fichier %s", nom_fic);
      exit(1);
  }
  printf(".............. Fermeture du fichier %s\n", nom_fic);

  return 0;
}
> more annuaire.txt
Contensin Magali 04 91 11 36 13 contensin@cmi.univ-mrs.fr
Alessandra Denis 04 91 11 36 13 alessand@club-internet.fr
Ifrah Sandrine 04 91 11 35 21 ifrah@cmi.univ-mrs.fr
> gcc -Wall annuaire.c -o annuaire
> ./annuaire annuaire.txt
.............. Ouverture du fichier annuaire.txt

        nom = Contensin
        prenom = Magali
        tel = 04 91 11 36 13
        mail = contensin@cmi.univ-mrs.fr

        nom = Alessandra
        prenom = Denis
        tel = 04 91 11 36 13
        mail = alessand@club-internet.fr

        nom = Ifrah
        prenom = Sandrine
        tel = 04 91 11 35 21
        mail = ifrah@cmi.univ-mrs.fr

le fichier annuaire.txt comporte 3 lignes
.............. Fermeture du fichier annuaire.txt
>

Écriture de données dans un fichier

fputs

La fonction int fputs(char *chaine, FILE *fic) écrit la chaîne de caractères chaine sur le flux fic. Elle retourne le dernier caractère de la chaîne en cas de succès (EOF en cas d'erreur).
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  FILE *fic; 
  int nb_lignes;
  char ligne_lue[512];

  // ouverture du fichier
  fic = fopen("resultat.txt", "w"); // ouvrir en ecriture
  if(fic == NULL){
      printf("Impossible d'ouvrir le fichier resultat.txt\n");
      exit(1);
  }

  do{
    fgets(ligne_lue, 512, stdin);
    fputs(ligne_lue, fic);
  }
  while(strcmp(ligne_lue, "FIN\n") != 0); 

  // fermeture du fichier
  if(fclose(fic) == EOF) {
      printf("Probleme de fermeture du fichier resultat.txt\n");
      exit(1);
  }
  
  printf("les donnees ont ete stockees dans resultat.txt\n");

  return 0;
}
> gcc ecritligne.c -o ecrit
> ./ecrit
FIN
les donnees ont ete stockees dans resultat.txt
> gcc ecritligne.c -o ecrit
> ./ecrit
premiere ligne entree sur la console
ceci est la deuxieme ligne
encore une ligne de test
FIN
les donnees ont ete stockees dans resultat.txt
> more resultat.txt
premiere ligne entree sur la console
ceci est la deuxieme ligne
encore une ligne de test
FIN
>

fprintf

La fonction int fprintf(FILE *fic, char *format, var_1, var_2, ...) écrit les données var_ dans le flux fic en respectant le format spécifié par la chaîne format. Elle retourne le nombre de caractères écrits sur le flux.
Le programme ci-dessous ajoute une entrée dans l'annuaire :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
  FILE *fic; 
  char nom_fic[255], nom[255], prenom[255], mail[255];
  int t1, t2, t3, t4, t5;

  // stockage des donnees issues de la ligne de commandes
  if(argc != 10){ //10 car num. tel. = 5 blocs d'entiers
    printf("Usage : annuaire nom_fichier nom prenom tel mail\n");
    exit(1);
  }
  strcpy(nom_fic, argv[1]);
  strcpy(nom, argv[2]);
  strcpy(prenom, argv[3]);
  strcpy(mail, argv[9]);
  t1 = atoi(argv[4]);
  t2 = atoi(argv[5]);
  t3 = atoi(argv[6]);
  t4 = atoi(argv[7]);
  t5 = atoi(argv[8]);

  // ouverture du fichier
  fic = fopen(argv[1], "a"); // ouvrir en ajout
  if(fic == NULL){
      printf("Impossible d'ouvrir le fichier %s\n", nom_fic);
      exit(1);
  }

  // ajouter les donnees dans l'annuaire
    fprintf(fic, "\n%s %s %.2d %.2d %.2d %.2d %.2d %s", nom, prenom, t1, t2, t3, t4, t5, mail);

  // fermeture du fichier
  if(fclose(fic) == EOF){
      printf("Probleme de fermeture du fichier %s", nom_fic);
      exit(1);
  }

  printf("Les informations ont ete stockees dans l'annuaire\n");

  return 0;
}
> gcc ecritannuaire.c -o ecrit
> more annuaire.txt
Contensin Magali 04 91 11 36 13 contensin@cmi.univ-mrs.fr
Alessandra Denis 04 91 11 36 13 alessand@club-internet.fr
Ifrah Sandrine 04 91 11 35 21 ifrah@cmi.univ-mrs.fr
> ./ecrit
Usage : annuaire nom_fichier nom prenom tel mail
> ./ecrit annuaire.txt Dupond Georges 04 94 13 22 11 dupond@bidule.net
Les informations ont ete stockees dans l'annuaire
> more annuaire.txt
Contensin Magali 04 91 11 36 13 contensin@cmi.univ-mrs.fr
Alessandra Denis 04 91 11 36 13 alessand@club-internet.fr
Ifrah Sandrine 04 91 11 35 21 ifrah@cmi.univ-mrs.fr
Dupond Georges 04 94 13 22 11 dupond@bidule.net
>
haut

0 comments:

Post a Comment