Le rôle des fichiers est multiple. Tout d'abord ils constituent une nouvelle structure de données munie de propriétés intéressantes. Ensuite ils donnent aux programmes le moyen de communiquer avec l'extérieur. Cette communication peut s'établir avec un terminal, ou un autre appareil: imprimante, lecteur de cartes, disques magnétiques. Le plus souvent cette communication s'établit avec le système sous lequel le programme s'exécute et permet de construire ou de consulter les ensembles de données qui existent avant ou après la période pendant laquelle le programme s'exécute.
Le Pascal utilise quelques concepts simples qui permettent d'utiliser de façon uniforme et portable une partie de ce qu'il est convenu d'appeler les opération sur les fichiers. Le Pascal standard permet seulement d'utiliser des fichiers séquentiels.
Un fichier séquentiel est un endroit ou l'on stocke des "fiches" de données de façon ordonnée, c'est à dire que les fiches sont rangées les unes après les autres en séquence.
D'un point de vue informatique, les fiches sont des objets d'un même type et leur nombre n'est pas fixé. Soit un type de données T déterminé, on peut construire un type "fichier" en écrivant:
file of T
On peut bien sûr donner un nom de ce type
TYPE
fichierdeT = file of T;
Et quand il y a un type déclaré, on peut
déclarer des variables de ce type:
f: FichierdeT;
Par exemple définissons le type fichier d'entier:
Type
Fichint = File of integer;
Var
f : Fichint;
La valeur de la variable f à un moment donné peut être représentée par une séquence d'emplacements d'entiers:
Si la séquence n'est pas vide, elle a un premier élément (25) et un dernier élément (3). Chaque élément sauf le dernier a un successeur. Certains éléments peuvent avoir la même valeur et l'ordre dans lequel ils sont rangés n'a pas à être en relation avec l'ordre de leurs valeurs.
Une telle séquence fait penser à un tableau à une dimension, mais il y a de nombreuses différences:
Un fichier doit pouvoir contenir un très gros volume d'information, qui ne peut pas être mis en entier dans la mémoire centrale. A cause de cette contrainte, à un moment donné, on ne pourra avoir accès qu'à l'un de ses éléments. Pour accéder à n'importe quel élément, il faut d'abord préparer le fichier. Cette opération se fait en deux étapes:
Si le nom du fichier dans l'appel de la procédure Assign n'est pas correct ou le fichier n'existe pas quand on essaie de l'ouvrir pour llecture, le système réagira par une erreur fatale et cessera l'exécution du programme. Mais cela n'est pas toujours la réaction désirée. Car c'est une réaction du système d'exploitation le Pascal standard n'a pas de moyens de réagir à telles erreurs. Mais presque chaque réalisation a des moyens pour franchir cette contrainte. Dans Turbo Pascal il y a les directives du compilateur. On écrit les directives comme les commentaires entre accolades. Mais le premier caractère de la directive est le signe de dollar ($) suivi par le caractère de la directive qui dénote l'action du compilateur, et le signe + ou - qui dénote si l'action est valide ou interdite.
Par exemple quand on veut suspendre les réactions standards d'entrée/sortie on écrit {$I-}
Exemple:
Type ouverture = (lire,ecrire); fichier = File of T; Procedure Ouvrir_le_fichier(var f : fichier; mode : ouverture); var succes : boolean); Var s : String[65]; err : integer; Begin write('Entrez le nom du fichier '); readln(s); Assign(f,s); {$I-} if mode = lire Then Reset(f) Else Rewrite(f); err := IOResult; |
{$I+} If err <> 0 Then Begin Write('Le fichier ',s); If mode = lire Then begin Write(' n''existe pas ou'); Writeln(' le nom n''est pas correct'); succes := False; End Else succes := True; End; |
Lire et écrire dans un fichier
Lecture des éléments (consulter le fichier)
On lit un élément par la procédure
read(<variable de type fichier>, <nom de variable de type
de base>)
La valeur de l'élément qui est désigné par le pointeur est copiée dans la variable et le pointeur se déplace vers l'élément suivant. Quand le pointeur du fichier arrive à la fin du fichier (la fin du fichier est atteinte) et qu'il n'y a pas un autre élément à lire, on dit qu'on est en fin de fichier. Il y a une fonction à résultat booléen - eof(f), qui est vrai si et seulement si la fin de fichier a été atteinte.
Construction d'un fichier
On écrit (ajoute) un élément avec:
write(<variable de type fichier>, <valeur de type de base>)
La valeur s'écrit à la fin du fichier, c'est à dire que quand on écrit, on est toujours en fin de fichier. Le pointeur se déplace à la fin et est prêt à écrire un nouvel élément.
Fermeture d'un fichier
Quand on a fini à utiliser le fichier f, on doit
le fermer avec
Close(f)
Puis le fichier peut être ouvert encore une fois, soit avec un nouveau nom, soit avec le nom existant.
Exemple: Ecrivez un programme qui lit un nombre indéfini de nombres réels, calcule leurs carrés et écrit ces derniers dans un fichier. Puis il lit les carrés et les affiche sur l'écran.
program fishier;
var fich:file of real;
a,carre : real;
begin
assign(fich,'carre.dat');
rewrite(fich);
while not eof do
begin
readln(a);
carre := sqr(a);
write(fich,a,carre);
end;
close (fich);
reset(fich);
while not eof(fich) do
begin
read(fich,a,carre);
writeln('Le carre de ',a:7:2,' est',carre:7:2);
end;
close(fich);
end.
Les fichiers "text" servent à travailler avec des données et des résultats écrits en clair, c'est à dire sous forme de caractères lisibles tels qu'on peut les taper sur un clavier ou les écrire sur un écran ou une imprimante. La notion de page est accessoire et n'a d'utilité que pour la sortie de résultats imprimés. La notion de ligne est beaucoup plus importante et doit être contrôlée précisément. En effet, si le découpage en pages est causé par des considérations esthétiques, le découpage en lignes est très important pour la signification des choses écrites.
On peut lire dans les manuels de Pascal que le type text
est un type prédéfini ainsi:
Type text = file of char;
Cette définition n'est pas complètement vraie particulièrement dans Turbo Pascal. Ici le type text est prédéfini, mais il y a quelques différences entre lui et le type file of char.
Exemple: Deux procédures qui permettent de transferer des nombres entiers entre la mémoire centrale et un fichier de type text.
Type Fichier = File of char; Procedure ReadInt(var f:fichier; var res:integer); Var c : char; sign : Boolean; Begin {Ommetre les blancs} Repeat Read(f,c); Until c <> ' '; res := 0; sign := True; {Lire le nombre entier} If c = '-' Then sign := False; While (c <'0') Or (c >'9') Do Read(f,c); While (c>='0') And (c <= '9') Do Begin res := res*10 + ord(c) - ord('0'); c := ' '; If not eof(f) Then read(f,c); End; If not sign Then res := -res; End; |
Procedure WriteInt(var
f:fichier; v,p:integer); var s:string; s1:string[15]; s2,s3: string[1]; sign : boolean; i : integer; Begin s := ''; s1[0] := chr(1); sign := v>=0; v := abs(v); s2 := '-'; s3 := ' '; Repeat s1[1] := chr(v mod 10 + ord('0')); Insert(s1,s,1); v := v div 10; Until v = 0; If not sign Then Insert(s2,s,1); For i:= Length(s)+1 To p Do Insert(s3,s,1); For i:=1 To Length(s) Do Write(f,s[i]); End; |
Devoir à la maison: Comment déclarer un
fichier dans lequel on peut écrire les valeurs de deux types différents
(par exemple nombres réels et valeurs logiques)?