
|
|
|
QBasic - L'accès aux fichiers
|
Autre langage disponible pour cet article :
Rubrique : QBasic
lundi 25 mars 2002 18:44
|
Voir les commentaires pour QBasic - L'accès aux fichiers
|
- Les fichiers à accès séquentiel
- Les fichiers à accès aléatoire
- Les fichiers binaires
- Fonctions et instructions complémentaires
- FREEFILE
- LOF
- LOC
- SEEK
Outre gérer les fichiers via le DOS, QBasic a aussi la capacité de lire les fichiers et d'écrire
dedans. Il existe trois types de fichiers. Les fichiers à accès séquentiel, les
fichiers à accès aléatoire et les fichiers binaires.
Les fichiers à accès séquentiel
Nous allons tout d'abord voir comment écrire dans un fichier. Pour écrire dans un fichier, il
faut déjà que celui ci existe. Si il existe, il n'y a qu'à l'ouvrir. Sinon, il faut le créer.
L'instruction OPEN est une instruction clef de l'accès aux fichiers. En effet, elle
sert aussi bien pour créer des fichiers, ou pour les ouvrir.
Pour créer un fichier, on utilise OPEN ainsi :
OPEN "C:\Warrior.txt" FOR OUTPUT AS #1
Détaillons. OPEN ouvre le fichier C:\Warrior.txt. FOR est utilisé pour préciser
le mode d'accès. Ici, le mode est OUTPUT (sortie in English), pour écrire. Ensuite,
il faut assigner à ce fichier un numéro par le biais du mot-clef AS. Ici, comme c'est
le premier fichier que l'on ouvre, on lui donne le numéro 1.
Maintenant, nous allons écrire dedans. Pour écriren, on utilise soit PRINT, soit WRITE.
La différence entre les deux, c'est que WRITE écrit avec des guillemets et des virgules entre
les termes.
On utilise PRINT comme pour écrire à l'écran. On rajoute seulement le numéro du fichier dans
lequel écrire :
OPEN "C:\Warrior.txt" FOR OUTPUT AS #1 ' ouverture du fichier en écriture
PRINT #1, "Ceci est un texte dans un fichier" ' écriture dans le fichier #1
CLOSE #1 ' fermeture
Dans cet exemple, le programme écrit la chaîne Ceci est un texte dans un fichier dans
le fichier #1 (C:\Warrior.txt).
L'instruction CLOSE ferme le fichier dont le numéro le suit. Il faut TOUJOURS
fermer un fichier, au mieux après son utilisation, au pis à la fin du programme, sinon les
effets peuvent être désastreux.
Maintenant, pour lire dans ce fichier, on utilise toujours OPEN, mais cette fois le mode d'accès
sera différent : on utilisera le mode INPUT.
' Création du fichier C:\Warrior.txt avec du texte à l'intérieur
OPEN "C:\Warrior.txt" FOR OUTPUT AS #1
PRINT #1, "Ceci est un texte dans un fichier"
CLOSE #1
' Lecture du fichier créé précédement
OPEN "C:\Warrior.txt" FOR INPUT AS #1
INPUT #1, Texte$
CLOSE #1
PRINT "Le texte du fichier est : "; Texte$
Que c'est-il passé ? On a tout simplement lu l'intérieur du fichier à l'aide de l'instruction
INPUT. La variable Texte$ qui suit INPUT prend alors la valeur de ce qui
doit être lu. Ensuite, on a fermé le fichier (TOUJOURS!), puis afficher le contenu de
la variable Texte$.
Maintenant, si on avait eu un nombre indéterminé de lignes dans le fichier, comment aurrait-on
fait ? Analysez ce petit programme de bloc-notes (sommaire). Il y a aussi une ou deux procédures.
COMMON SHARED Fichier$
Fichier$ = "C:\Notes.txt"
CLS
DO
PRINT "[L]ire | [E]crire | [Q]uitter"
DO
Touche$ = UCASE$(INKEY$)
LOOP UNTIL Touche$ <> ""
SELECT CASE Touche$
CASE "L"
Lire
CASE "E"
Ecrire
END SELECT
LOOP UNTIL Touche$ = "Q"
END
SUB Ecrire()
' Cette procédure ecrit dans le fichier
CLS
PRINT "Ecrire sautez une ligne pour finir"
PRINT
OPEN Fichier$ FOR OUTPUT AS #1
DO
LINE INPUT Texte$
PRINT #1, Texte$
LOOP UNTIL Texte$ = ""
CLOSE #1
END SUB
SUB Lire()
' Cette procédure lit le contenu du fichier et l'affiche
CLS
PRINT "*** Bloc-Notes ***"
PRINT
OPEN Fichier$ FOR INPUT AS #1
DO UNTIL EOF(1) = -1
LINE INPUT #1, Ligne$
PRINT Ligne$
LOOP
CLOSE #1
END SUB
Certaines instructions n'ont encore pas été vues jusqu'ici :
- INKEY$ : cette instruction renvoie l'état d'une touche du clavier lors de son
appelle. C'est à dire que si la touche 'T' est enfoncée,
INKEY$ vaudra 'T'. Mais si la
touche était 't', INKEY$ vaudrais 't'. C'est pourquoi on converti le retour de INKEY$ en
lettres majuscules à l'aide de l'instruction UCASE$.
- EOF :
EOF renvoi -1 (TRUE) si la fin du fichier dont le numéro lui est associé est
atteinte. Le numéro est le celui entre parenthéses (ici, 1).
- LINE INPUT : on a tout simplement rajouté
LINE devant INPUT. Cette associtation
a pour effet de lire une ligne de 255 caractères, que ce soit sur l'écran ou dans un
fichier.
On peut dire que ce petit programme est structuré, puisque l'on a respecté une certaine méthode.
- Dans la boucle
DO...LOOP, on commence par afficher le menu rudimentaire.
- Ensuite l'execution du programme est suspendue jusqu'à ce que l'utilisateur appuie sur
une touche.
- Puis, à l'aide d'une structure
SELECT...CASE, on analyse la commande et on la traite.
Si la commande est 'L' (Lire le fichier), on execute la procédure 'Lire'. Si la commande
est 'E' (Ecrire dans le fichier), on execute la procédure 'Ecrire'. En revanche, si la
commande est 'Q' (Quitter), on sort de la boucle, ce qui a pour effet de terminer le
programme avec l'instruction END.
Détaillons maintenant les deux procédures :
- Ecrire : cette procédure écrit dans le fichier définit au départ dans la variable
Fichier$. Pour cela, on ouvre le fichier avec OPEN et l'accés OUTPUT, pour
pouvoir écrire dedans. On lui attribut le numéro 1.
Puis on rentre dans une boucle DO...LOOP. Cette boucle demande à l'utilisateur d'entrer
du texte. Ce texte est ensuite écrit dans le fichier. Si l'utilisateur entre une ligne
vierge, la boucle se termine. Le fichier est alors refermé avec l'instruction CLOSE.
- Lire : cette procédure lit le fichier et affiche le contenu sur l'écran. Le fichier
est comme d'habitude ouvert avec l'instruction
OPEN. Cependant, le mode d'accès différe
puisqu'on utilise INPUT.
Et comme dans la procédure détaillée précédemment, on entre dans une boucle DO...LOOP.
On lit alors toute une ligne du fichier avec LINE INPUT puis on l'écrit sur l'écran avec
PRINT. La boucle se termine lorsque la fin du fichier est atteinte, c'est à dire lorque
EOF vaut -1 (TRUE). Puis on referme le fichier.
Mais vous aurrait certainement remarqué qu'à chaque fois que l'on veut écrire dans le fichier,
l'ancien contenu est effacé. Si on avait voulu écrire à la suite et conservé les anciennes données,
il aurrait falut utiliser un autre mode d'accès que OUTPUT : APPEND.
APPEND ouvre le fichier en écriture, tout comme OUTPUT, mais à ce détail près que toutes les
informations sont écrite à la fin du fichier. Modifiez donc le mode d'accès de la procédure
Ecrire de notre précédent exemple par APPEND.
COMMON SHARED Fichier$
Fichier$ = "C:\Notes.txt"
CLS
DO
PRINT "[L]ire | [E]crire | [Q]uitter"
DO
Touche$ = UCASE$(INKEY$)
LOOP UNTIL Touche$ <> ""
SELECT CASE Touche$
CASE "L"
Lire
CASE "E"
Ecrire
END SELECT
LOOP UNTIL Touche$ = "Q"
END
SUB Ecrire()
' Cette procédure ecrit dans le fichier
CLS
PRINT "Ecrire sautez une ligne pour finir"
PRINT
OPEN Fichier$ FOR APPEND AS #1 ' changement du mode d'accès
DO
LINE INPUT Texte$
PRINT #1, Texte$
LOOP UNTIL Texte$ = ""
CLOSE #1
END SUB
SUB Lire()
' Cette procédure lit le contenu du fichier et l'affiche
CLS
PRINT "*** Bloc-Notes ***"
PRINT
OPEN Fichier$ FOR INPUT AS #1
DO UNTIL EOF(1) = -1
LINE INPUT #1, Ligne$
PRINT Ligne$
LOOP
CLOSE #1
END SUB
Comme prévu, les lignes sont belles et biens rajoutées à la fin du fichier.
Ce qu'on ne vous a pas dit :
- Lors de l'ouverture d'un fichier avec les modes d'accés
INPUT et APPEND, le fichier
doit OBLIGATOIREMENT exister. Dans le cas contraire, une erreur 'Fichier non
trouvé' se produit.
- Comme pour du texte à l'écran, on peut utiliser l'instruction PRINT USING pour
écrire du texte en forme, avec le numéro du fichier après
PRINT, naturellement.
Les fichiers à accès aléatoire
Vous avez vu que les fichiers à accès séquentiel ne permettent pas d'aller directement à un
enregistrement bien déterminé. C'est pourquoi il existe une autre race de fichiers : les fichiers
à accès aléatoire.
Ce dernier mode d'accès est très utile pour réaliser des bases de données. En fait, ces fichiers
permettent d'enregistrer un type définit par l'utilitsateur. Ainsi, pour un fichier qui aurrait
gérer les clients d'une société, on aurrait pu écrire un programme tel que celui-ci :
TYPE TClient
Numero AS INTEGER
Societe AS STRING * 30
Nom AS STRING * 30
Prenom AS STRING * 30
Telephone AS STRING * 30
Fax AS STRING * 30
Email AS STRING * 30
END TYPE
COMMON SHARED Fichier$
Fichier$ = "C:\Clients.txt"
DO
PRINT "[N]ouveau client | [A]ller à | [Q]uitter"
DO
Touche$ = UCASE$(INKEY$)
LOOP UNTIL Touche$ <> ""
SELECT CASE Touche$
CASE "N"
Nouveau
CASE "A"
Aller
END SELECT
LOOP UNTIL Touche$ = "Q"
END
SUB Nouveau()
DIM Client AS TClient
CLS
PRINT "*** Création d'un nouveau client ***"
PRINT
INPUT "Numéro client : ", Client.Numero
INPUT "Société : ", Client.Societe
INPUT "Nom : ", Client.Nom
INPUT "Prénom : ", Client.Prenom
INPUT "Telephone : ", Client.Telephone
INPUT "Fax : ", Client.Fax
INPUT "Email : ", Client.Email
OPEN Fichier$ FOR RANDOM AS #1 LEN = LEN(Client)
PUT #1, Client.Numero, Client
CLOSE #1
END SUB
SUB Aller()
DIM Client AS TClient
CLS
PRINT "*** Aller à un numéro de client ***"
PRINT
INPUT "Numéro du client à rechercher : ", Numero
OPEN Fichier$ FOR RANDOM AS #1 LEN = LEN(Client)
GET #1, Numero, Client
CLOSE #1
PRINT "Société : ", Client.Societe
PRINT "Nom : ", Client.Nom
PRINT "Prénom : ", Client.Prenom
PRINT "Telephone : ", Client.Telephone
PRINT "Fax : ", Client.Fax
PRINT "Email : ", Client.Email
END SUB
L'utilisation de ce programme est très simple. Pour créer un client, on appuie sur la touche 'n'.
À ce moment, il faut préciser le numéro du client. Attention ! Si un client était déjà affecté
à se numéro, les données seront écrasées.
Si on veut retrouver une fiche client, on appuie sur la touche 'A'. L'ordinateur demande alors
le numéro de la fiche à laquelle il doit aller.
Bien sur, on aurrait put créer des routines, des procédures et des fonctions permettant de
rechercher, filtrer, classer, compter, anlyser les enregistrements, mais le but de ce chapitre
est une simple démonstration des capacités des fichiers à accès aléatoire.
Mais regardons plutôt comment ça marche. Passons sur le corps principal du programme, vous êtes
désormais familiarisé avec ce genre de menu. Remarquez seulement la définition du type. Comme
c'est un type, tout les champs STRING doivent être délimités. Ici on a mis 30 caractères, mais
on aurrait tout a fait pu en mettre 50 ou 5. Le principal, c'est qu'il soit définis.
Allons voir ce qu'il ce passe dans la procédure 'Nouveau'. Déjà, on déclare une variable 'Client'
du type 'TClient' définit précédemment. Puis, à l'aide des instructions INPUT, on assigne des
valeurs au différents champs.
Ensuite, il faut stocker ces données dans le fichier. On ouvre alors le fichier avec OPEN,
et le mode d'accès RANDOM, pour un accès aléatoire. Comme nous somme en mode aléatoire,
il faut spécifier la longueur de chaque enregistrement avec LEN en octets.
Attention ! Il ne faut pas confondre ces deux LEN ! Le premier posséde une valeur qui est définie
par l'autre instruction LEN. Comme vous le savez, LEN donne la longueur d'une chaîne de caractères.
Dans ce contexte, LEN donne le nombre d'octets occupé par la variable 'Client'. On aurrait tout
aussi bien pu mettre une constante d'octets que l'on aurrait calculé à partir de notre type :
Numéro (2 octets) + Societe (30 octets) + Nom (30 octets) + Prenom (30 octets) + Telephone (30
octets) + Fax (30 octets) + Email (30 octets) = 182 octets. Donc, la ligne aurrait pu s'écrire :
OPEN Fichier$ FOR RANDOM LEN = 182
Ensuite, comme pour un fichier séquentiel, il faut stocker les données. Mais ici, c'est avec
PUT qu'il faut oppérer.
On spécifie le numéro du fichier, le numéro de l'enregistrement, puis la variable A ECRIRE.
Et comme un fichier traditionnel, on le referme.
Pour la procédure 'Aller', c'est presque pareil. On définit la variable, on demande le numéro
de l'enregistrement à consulter, on ouvre le fichier avec RANDOM sans oublier de fixer la taille
des enregistrements, puis là on utilise non pas PUT, non pas INPUT, ni LINE INPUT, mais GET
pour accéder à l'enregistrement spécifié.
Avec GET, on spécifie le numéro du fichier, le numéro de l'enregistrement, puis la variable où
l'on va STOCKER la lecture du fichier.
Ensuite, on a afficher la variable.
Les fichiers binaires
À proprement parler, les fichiers binaires ne sont pas un type disinct. En fait, ouvrire un
fichier en mode d'accès binaire permet de modifier n'importe quel octet à n'importe quel emplacement.
Le mode d'accès binaire va ouvrir le fichier sans prendre en compte les éventuelles liaisons
qu'il pourrait y avoir si c'était un fichier à accès aléatoire.
Voici un exemple qui ouvre un fichier de votre choix et affiche son contenu à la manière d'un
éditeur Hexadécimal.
SCREEN 0
WIDTH 80, 50
DIM Octet AS STRING * 1
INPUT "Nom du fichier à ouvrir : ", Fichier$
CLS
OPEN Fichier$ FOR BINARY AS #1
FOR i = 1 TO LOF(1)
GET #1, i, Octet
PRINT HEX$(ASC(Octet)) + SPACE$(1);
IF i / 4 = INT(i / 4) THEN PRINT ,
IF i / 16 = INT(i / 16) THEN
FOR j = i - 15 TO i
GET #1, j, Octet
IF Octet < SPACE$(1) THEN Octet = SPACE$(1)
PRINT Octet;
NEXT j
PRINT : PRINT
END IF
NEXT i
CLOSE #1
Comme il est désormais coutume avec les fichiers, on ouvre le fichier avec OPEN. Ici, le mode
d'accès s'appelle BINARY. Ensuite, on entre dans une boucle. L'instruction LOF
retourne la longueur en octets du fichiers dont le numéro lui est passé. Ensuite, pour lire un
octet, on utilise GET, suivit du numéro du fichier, de l'octet à lire, et de la variable
dans laquelle stocker la lecture. Tout le reste, les IF...THEN, ASC, HEX$, INT, FOR...NEXT, PRINT
n'est que mise en scène afin d'afficher de manière propre les données.
Maintenant, si on avait voulu écrire au lieu de lire, on aurrait tout simplement utilisé l'
instruction PUT, suivit du numéro du fichier dans lequel écrire, de l'emplacement de l'
octet où écrire et de la variable contenant la valeur de l'octet.
Fonctions et instructions complémentaires
FREEFILE
À chaque fois que l'on ouvre un fichier alors que d'autres sont déjà ouverts, il faut lui allouer
un numéro. Or, il arrive que dans des programmes employant des boucles ou autres, on ne sache
pas quel numéro employer. Heuresement, l'instruction FREEFILE est là et renvoi le prochain
numéro de fichier disponible :
Num = FREEFILE ' FREEFILE renvoi le prochain numéro
' de fichier disponible
OPEN "C:\Notes.txt" FOR INPUT AS Num
CLOSE Num
LOF
Il est parfois utile de connaître la longueur d'un fichier, pour une raison ou pour une autre.
LOF (Length Of File) renvoi la longueur (en octets) du fichier dont le numéro
lui est passé en argument. Le fichier doit donc être ouvert pour pouvoir être pesé :
OPEN "C:\Notes.txt" FOR INPUT AS #1
PRINT "La taille du fichier est de "; LOF(1); " octets."
CLOSE #1
LOC
Lorsqu'un fichier est ouvert, si on veut connaître la position actuelle du pointeur dans le fichier,
on utilise l'instruction LOC. LOC n'a pas le même effet selon le type d'accès du fichier :
- Accès séquentiel : retourne la position de l'octet pointé, mais divisé par 128.
- Accès aléatoire : renvoi le numéro du dernier enregistrement lu ou écrit.
- Accès binaire : retourne la position du dernier octet lu ou écrit.
SEEK
SEEK est un peu particulier, puisque c'est à la fois une fonction et une instruction (pour
rappel, une fonction renvoi une valeur, alors qu'une instruction non).
La fonction retourne la postion actuelle du pointeur dans un fichier.
L'instrucion spécifie la position de ce même pointeur pour la prochaine opération d'écriture ou
de lecture.
|
Voir les commentaires pour QBasic - L'accès aux fichiers
|
|
|
|