Cours de Turbo Pascal 7


précédentsommairesuivant

Chapitre 10 - Manipulation des fichiers

Déclaration

Pour utiliser un ou des fichiers tout au long d'un programme ou dans une procédure, il faudra l'identifier par une variable dont le type est fonction de l'utilisation que l'on veut faire du fichier.

Il existe trois types de fichiers :

Les fichiers textes (Text)

Les fichiers textes (Text) sont écrits au format texte (chaînes de caractères, nombres) dans lesquels ont peut écrire et lire ligne par ligne ou à la file avec les procédures Write(Ln) et Read(Ln). Chaque fin de ligne du fichier se termine par les caractères 10 et 13 de la table ASCII (qui signifient respectivement Retour ligne (Line Feed, LF) = #10 et Retour chariot (carriage return, CR) = #13). Ces deux derniers caractères sont transparents au programmeur.
On pourra donc écrire ou lire indifféremment des chaînes ou des nombres, cela dépend du type que l'on affecte à la variable passée en paramètre aux procédures d'entrée/sortie (voir plus bas).

S'il y a lieu de faire une conversion nombre/chaîne, le compilateur le fait tout seul. Par contre, si le type de la variable ne correspond pas avec la donnée lue dans le fichier et qu'aucune conversion n'est possible alors cela produit une erreur.

Syntaxe :

 
Sélectionnez

Var f : Text;

Les fichiers typés (File of ...)

Les fichiers typés (File of) sont des fichiers dans lesquels les données sont écrites telles qu'elles se présentent en mémoire. On dit qu'elles sont écrites dans leur représentation binaire. La taille du fichier résultera directement et exactement de la taille en mémoire qu'occupe telle ou telle variable.
Cela accroît la vitesse d'accès aux données du fichier. Mais le plus grand avantage c'est que l'on obtient ainsi des fichiers parfaitement formatés, c'est-à-dire qu'on peut y lire et écrire directement des variables de type structuré qui contiennent plusieurs champs de données sans avoir à se soucier des divers champs qu'elles contiennent.

Syntaxe :

 
Sélectionnez

Var f : File of {type};

Exemple :

 
Sélectionnez

Var f : File of Integer;

Les fichiers simples (File)

Les fichiers... tout court ! (File) sont des fichiers dont on ne connaît pas le contenu. Ils peuvent servir à faire une simple copie d'un fichier dans un autre, pour stocker des données de différents types (en se donnant les moyens de retrouver ce que sont ces types lors de la lecture), pour sauver tout le contenu d'une zone mémoire pour analyse ultérieure, etc.

Syntaxe :

 
Sélectionnez

Var f : File;

Lecture et écriture

Avant de travailler sur un fichier, il faut le déclarer en lui affectant une variable qui servira à désigner le fichier tout au long du programme ou de la procédure dans laquelle il est utilisé. Assign s'applique à tous les types de fichiers.

Syntaxe :

 
Sélectionnez

Assign (variable_d_appel, nom_du_fichier);

Ensuite, il faut ouvrir le fichier.

Syntaxe :

 
Sélectionnez

Reset (variable_d_appel);

On ne peut pas écrire dans un fichier Text ouvert avec Reset !

Il est possible, pour le type File uniquement, de spécifier la taille de chaque bloc de donnée lu ou écrit sur le fichier, en rajoutant en argument à Reset une variable (ou un nombre directement) de type Word (entier) spécifiant cette taille en octet. Cela nécessite de connaître la taille mémoire de chaque type de variable (voir chapitre 4 sur les différents types de variables) - la fonction SizeOf sert à cela. Par exemple, cette taille vaudra 6 si on veut lire des nombres réels (Real) ou bien 256 pour des chaînes de caractères (String). Le fait que la variable taille soit de type Word implique que sa valeur doit être comprise entre 0 et 65535. Par défaut, taille = 128 octets.

Syntaxe :

 
Sélectionnez

Reset (variable_d_appel, taille);

Pour créer un fichier qui n'existe pas ou bien pour en effacer son contenu, on emploie Rewrite qui permet d'effectuer des lectures (File of et File) et écritures (Text, File of et File).

On ne peut pas lire dans un fichier Text ouvert avec Rewrite !

Syntaxe :

 
Sélectionnez

Rewrite (variable_d_appel);

L'utilisation de Rewrite avec un fichier existant ouvre ce fichier, mais le vide !

Tout comme Reset, Rewrite permet de spécifier une taille aux échanges de données sur un File seulement (aussi bien en écriture qu'en lecture). Avec Rewrite, dans le cas où le fichier n'existe pas encore alors qu'avec Reset c'est dans le cas où il existe déjà.

Syntaxe :

 
Sélectionnez

Rewrite (variable_d_appel, taille);
Tableau des correspondances entre procédures et types de fichiers
Syntaxe Lecture Ecriture
Reset(f) Text
File of
File
File of
File
Rewrite(f) File of
File
Text
File of
File
Reset(f,taille) File File
Rewrite(f,taille) File File



Pour lire le contenu d'une ligne d'un fichier Text ouvert, on utilise la même instruction qui permet de lire la valeur d'une variable au clavier à savoir ReadLn. (2) Sera alors lue, la ou les variable(s) correspondant au contenu de la ligne courante (celle pointée par le pointeur). Si la ou les variable(s) n'étai(en)t pas de taille suffisante pour contenir toutes les données de la ligne, alors l'excédent serait perdu. C'est même un peu plus compliqué que ça : si on lit une variable de type String, la lecture se poursuivra jusqu'à la fin de la ligne en cours, ou jusqu'à la fin du fichier si elle survient avant, et cela quelle que soit la longueur maximale possible pour la chaine. Il faut donc faire très attention.

Syntaxes :

 
Sélectionnez

ReadLn (variable_d_appel, variable);
ReadLn (variable_d_appel, var1, var2, ... varN); { Attention, pas de Strings (sauf la dernière) }

Pour écrire dans un fichier Text, il suffit d'employer la procédure WriteLn. (3)

Syntaxes :

 
Sélectionnez

WriteLn (variable d_appel, variable);
WriteLn (variable_d_appel, var1, var2, ... varN); { Attention : voir la remarque ci-après }

Il faut éviter cette seconde syntaxe, à moins de préciser, pour chaque variable à écrire, la largeur minimum à utiliser, en prenant soin que pour tous les cas possibles cette largeur minimum garantisse qu'il y aura au moins un espace pour séparer les données de chaque variable, sinon on ne pourra pas relire correctement les données.

Pour lire et écrire sur un File, il faut utiliser les procédures BlockRead et BlockWrite.

Syntaxes :

 
Sélectionnez

BlockRead (f, variable, nbr);
BlockRead (f, variable, nbr, result);
BlockWrite (f, variable, nbr);
BlockWrite (f, variable, nbr, result);

BlockRead lit sur le fichier f de type File une variable qui contiendra un nombre de blocs mémoire (dont la taille est définie par Reset ou Rewrite) égale à nbr. La variable (facultative mais dont l'utilisation systématique est fortement conseillée) result prend pour valeur le nombre de blocs effectivement lus (car il peut y en avoir moins que prévu initialement).

BlockWrite écrit sur le fichier f de type File une variable sur un nombre de blocs mémoire égal à nbr. La variable (facultative mais dont l'utilisation systématique est fortement conseillée) result prend pour valeur le nombre de blocs effectivement écrits. Dans le cas ou cette variable result est ommise et qu'il est impossible d'écrire autant de blocs que voulu, il est généré une erreur d'exécution !

Les variables nbr et result doivent être de type Word.

Tableau des correspondances entre procédures et types de fichiers
Syntaxe Types de fichiers associés
WriteLn Text
ReadLn Text
Write Text
File of
Read Text
File of
BlocWrite File
BlockRead File

Fermeture

Il est impératif de fermer les fichiers ouverts avant de terminer le programme, sous peine de voir les données inscrites en son sein perdues.

Syntaxe :

 
Sélectionnez

Close (variable_d_appel);

Il est possible de rouvrir un fichier Text en cours de programme même s'il a déjà été refermé, grâce à sa variable d'appel. La position courante du curseur sera alors positionnée à la fin du fichier. Cela ne fonctionne qu'en écriture et qu'avec un Text.

Syntaxe :

 
Sélectionnez

Append (variable_d_appel);

Exemple :

 
Sélectionnez

Program Exemple12;

Uses 
  Crt, Dos;

Var 
  f : Text;
  Nom : String;
  Choix : Char;

Procedure Lecture;
Begin
  Append(f);
  Readln(f,nom);
  Writeln(nom);
End;

BEGIN
  Clrscr;
  Assign(f,'init.txt');
  Rewrite(f);
  Write('Entrez un nom d''utilisateur : ');
  Readln(Nom);
  Nom := 'Dernier utilisateur : ' + Nom;
  Writeln(f,Nom) ;
  Close(f);
  Write('Voulez-vous lire le fichier init.txt ? [O/N] ');
  Choix := ReadKey;
  if (UpCase(Choix) = 'O') then Lecture;
END.

Ce programme Exemple12 illustre les principales commandes qui permettent de travailler sur des fichiers de type texte. Ici, le programme réinitialise à chaque lancement le fichier init.txt et y inscrit une valeur entrée par l'utilisateur (son nom, en l'occurrence). Il permet également à l'utilisateur de lire le contenu du fichier (qui ne contient qu'une seule ligne de texte).

Fonctions supplémentaires

Gestion du curseur

Il est possible de déplacer à volonté le curseur en spécifiant à la procédure suivante le fichier de type File of ou File ainsi que le numéro de l'élément (le premier à pour numéro :"0", le second : "1", le troisième : "2", etc...) où l'on veut mettre le curseur. Cela s'appelle l'accès direct à un fichier contrairement à l'accès séquentiel qui consiste à parcourir toutes les informations précédant celle qu'on cherche.
Note : Seek n'est pas utilisable avec des Text.

Syntaxe :

 
Sélectionnez

Seek (variable_d_appel, position);

Exemple :

 
Sélectionnez

Program Exemple13 ;
Uses 
  Crt, Dos;
Var 
  f : Text;
  s : String ;
BEGIN
  Assign(f,'c:\autoexec.bat');
  Reset(f);
  Writeln('Affichage du contenu du fichier AUTOEXEC.BAT : ');
  while not Eof(f) do
    begin
      ReadLn(f,s);
      WriteLn(s);
    end;
END.

Ce programme Exemple13 permet de lire un fichier texte et d'en afficher le contenu à l'écran. La fonction Eof permet de vérifier si le pointeur arrive en fin de fichier (elle aura alors la valeur true).
Il est possible de connaître la taille d'un fichier en octets, sauf lorsque celui-ci est déclaré en Text.

Syntaxe :

 
Sélectionnez

FileSize (variable_d_appel);

Il est possible de connaître la position du pointeur, en octets, dans le fichier lorsque celui-ci est déclaré en File of Byte. La fonction suivante renvoie une valeur de type LongInt.

Syntaxe :

 
Sélectionnez

FilePos (variable_d_appel);

Exemple :

 
Sélectionnez

Program Exemple14;
Var 
  f : File of Byte;
  Taille : LongInt;
BEGIN
  Assign(f,'c:\autoexec.bat');
  Reset(f);
  Taille := FileSize(f);
  Writeln('Taille du fichier en octets :',Taille);
  Writeln('Déplacement du curseur...');
  Seek(f,Taille div 2);
  Writeln('Le pointeur se trouve à l''octet : ',FilePos(f));
  Close(f);
END.

Le programme Exemple14 déclare le fichier autoexec.bat comme File of Byte et non plus comme Text, puisqu'on ne désire plus écrire ou lire du texte dedans mais seulement connaître sa taille et accessoirement faire mumuse avec le pointeur.

Fin de ligne, fin de fichier

Il est possible de savoir si, lors de la lecture d'un fichier, on se trouve ou non en fin de ligne ou de fichier, grâce aux fonctions suivantes qui renvoient une valeur de type Boolean.

Syntaxe :

 
Sélectionnez

Var f : Text;
Eof(f); { Pointeur en fin de fichier }
SeekEoLn(f); { Pointeur en fin de ligne }

Autre syntaxe :

 
Sélectionnez

Var f : File;
EoLn (f); { Pointeur en fin de ligne }
SeekEof (f); { Pointeur en fin de fichier }

Exemple :

 
Sélectionnez

Program Exemple15 ;
Var 
  f : Text;
  i, j : String;
BEGIN
  Assign(f,'c:\autoexec.bat');
  Reset(f);
  while not SeekEof (f) do
    begin
      if SeekEoln(f) then ReadLn(f);
      Read(f,j);
      Writeln(j);
    end;
END.

Effacer un fichier

On peut également effacer un fichier préalablement fermé.

Syntaxe:

 
Sélectionnez

Erase (f);

Renommer un fichier

On peut aussi renommer un fichier (qui ne doit pas être ouvert).

Syntaxe :

 
Sélectionnez

Rename (f, NouveauNom);

Tronquer un fichier

Il est possible de tronquer un fichier, c'est-à-dire de supprimer tout ce qui se trouve après la position courante du pointeur.

Syntaxe :

 
Sélectionnez

Truncate (f);

Gestion des erreurs

Dans tous les exemples de manipulation de fichiers donnés jusqu'ici, il n'a pas été tenu compte (pour des raisons de clarté, pour présenter les différentes notions) des éventuelles erreurs qui auraient pu survenir.
En effet, si on laisse les choses en l'état, la moindre erreur de création, d'ouverture, de lecture, d'écriture de fichier provoquera une terminaison immédiate et inconditionnelle du programme. Or, il y a moyen d'intercepter proprement toutes ces erreurs et d'offrir à l'utilisateur un produit mieux fini.

La première chose à faire est de donner une directive au compilateur, lui demandant non pas de mettre fin au programme en cas d'erreur, mais plutôt d'aller indiquer un code d'erreur dans une variable interne que le programme pourra consulter. Cette directive est

 
Sélectionnez

{$I-}

Après chaque exécution d'une routine de gestion de fichier, le programme pourra aller tester la valeur de cette variable interne, au moyen de la fonction IOResult.

Exemple : une procédure de copie de fichier :

 
Sélectionnez

Function CopyFile (const SourceFile, DestFile : String) : Boolean;
Var
  Source, Dest : File;
  Buffer : Array [0..1023] of Byte;
  Count : Word;
  OldFileMode : Word;
Begin
  CopyFile := True;
  { Désactivation des erreurs E/S }
  {$I-}

  { Assignation des fichiers }
  Assign(Source,SourceFile);
  Assign(Dest,DestFile);

  { Ouverture en lecture seule de Source et création de Dest }
  OldFileMode := FileMode;
  FileMode := 0;
  Reset(Source,1);
  if IOResult = 0
     then
       begin
         Rewrite(Dest,1);
         if IOResult = 0
            then
              begin
                { Boucle principale de copie, s'arrête quand la fin du fichier est atteinte }
                repeat
                  { Remplissage du buffer : 1 Ko prévus, Count octets réels }
                  BlockRead(Source,Buffer,SizeOf(Buffer),Count);
                  { Ecriture du contenu du buffer }
                  BlockWrite(Dest,Buffer,Count);
                until (Count = 0) or (Count <> SizeOf(Buffer));
                { Fermeture du fichier }
                Close(Dest);
                if IOResult <> 0
                   then   { Erreur de fermeture du nouveau fichier }
                     CopyFile := False;
              end
            else   { Erreur de création du nouveau fichier }
              CopyFile := False;
         { Fermeture du fichier }
         Close(Source);
       end
     else   { Erreur d'ouverture du fichier original }
       CopyFile := False;
  { Réactivation des erreurs d'E/S et rétablissement du mode de lecture }
  FileMode := OldFileMode;
  {$I+}
End;

Notez que le mode normal de gestion des erreurs est restauré à la fin de la procédure, avec la directive

 
Sélectionnez

{$I+}

précédentsommairesuivant
On peut également utiliser Read, mais cela peut poser des problèmes car en arrivant à la fin de la ligne, le pointeur ne passera pas à la suivante si on n'utilise que des Read.
On peut également utiliser Write, avec la même remarque que pour le Read.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2001-2013 Hugo Etievant. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.