8.1 LA GESTION DES FICHIERS – INPUT/OUTPUT

Un fichier est une collection de données répétitives analogues portant sur des individus ou des objets différents. Un fichier est un ensemble d’enregistrements différents mais contenant le même genre de structure.
Un tel ensemble pourrait très bien se trouver en mémoire centrale mais nous ne parlerons de fichier que lorsque l’ensemble des informations se trouve sur un périphérique externe disque ou bande.

On utilise des fichiers pour plusieurs raisons, tout d’abord par opposition avec la mémoire ou dés la fermeture de l’ordinateur toutes informations en mémoire est perdue, sur disque nous pouvons les conserver le temps nécessaire.
Les mémoires centrales sont limitées et la masse d’information à traiter peut être supérieure à l’espace disponible.
Les données contenues dans un fichier peuvent être utilisées par différents programmes et peuvent même être échangées entre ordinateurs.

Le COBOL permet 3 types d’organisations de fichier :
– l’organisation séquentielle
– l’organisation séquentiel indexée
– l’organisation relative.

Par organisation, il faut entendre la façon dont le fichier est organisé physiquement sur le support et l’accès à un enregistrement est la manière que nous utilisons pour atteindre cet enregistrement.

Un accès est dit séquentiel lorsque pour lire le 25ème
record du fichier, il est obligatoire de lire les 24 précédents. C’est ce type d’accès qui est utilisé sur bande magnétique.

Un accès est dit sélectif lorsqu’un record bien précis du fichier peut être atteint sans devoir lire tous ceux qui le précédent. Ce type d’accès oblige l’utilisation d’une clé permettant de retrouver la position de l’enregistrement dans le fichier. Ce type d’accès ne s’utilise que pour les périphériques disques.
Tous les ordres d’entrées-sorties ne concernent toujours qu’un seul enregistrement à la fois.
Cobol oblige le programmeur à ouvrir chaque fichier par un ordre OPEN avant de pouvoir lire ou écrire sur un fichier. De même, chaque fichier sera fermé par une instruction CLOSE en fin de travail.

OUVERTURE DES FICHIERS OPEN

Un ordre d’ouverture de fichiers OPEN doit être donné pour tous les fichiers utilisés dans le programme en séparant les fichiers ENTREE de lecture INPUT, des fichiers SORTIE en écriture OUTPUT et EXTEND. Cette instruction OPEN doit toujours précéder les instructions de lecture ou d’écriture.

              |  INPUT   nom-de-fichier-1  |
Format : OPEN |  OUTPUT  nom-de-fichier-2  |
              |  I-O     nom-de-fichier-3  |
              |  EXTEND  nom-de-fichier-4  |

Un fichier ne peut être cité qu’une seule fois dans une clause OPEN.
Il n’est pas obligatoire d’ouvrir tous les fichiers en même temps.

Un fichier ne doit être ouvert qu’une fois, un second passage dans la même instruction OPEN sans être passé par une instruction CLOSE pour ce fichier entraîne une erreur dans le programme.
L’ouverture d’un fichier positionne le pointeur d’enregistrement au début du fichier sauf pour l’ouverture en EXTEND.

La clause INPUT déclare que le fichier est ouvert uniquement pour être lu. Donc ce fichier doit déjà exister.

La clause OUTPUT déclare que le fichier est ouvert uniquement pour qu’on y écrive. Si le fichier existe déjà avec ses enregistrements, un OPEN OUTPUT les efface, le fichier est alors vidé de son contenu, et un nouveau fichier est créé.

La clause I-O déclare un fichier comme étant ouvert en même temps en lecture et en écriture.

La clause EXTEND déclare le fichier comme étant ouvert en écriture, le fichier n’est pas vidé de son contenu, le pointeur d’enregistrement se positionne à la fin du fichier. Seul un fichier à organisation séquentiel peut être ouvert en extend.

Un essai d’ouverture en lecture d’un fichier non existant génère une erreur d’exécution.

Exemple :
OPEN INPUT FICH1 FICH2
     OUTPUT IMPR FPCLIENT.

OPEN INPUT FICH1.
OPEN INPUT FICH2.
OPEN OUTPUT IMPR.
OPEN OUTPUT FPCLIENT.

Nous obtenons le même résultat dans les 2 cas mais le premier est plus rapide.

FERMETURE DES FICHIERS – CLOSE.

Format :
CLOSE nom-de-fichier1 nom-de-fichier2 ….

Un ordre de fermeture doit être donné pour tous les fichiers utilisés, donc ouverts et ceci avant l’instruction STOP RUN. Dans cette instruction on ne fait pas de distinction entre les fichiers INPUT ou OUTPUT, tous les fichiers peuvent être fermés en même temps.
Exemple : CLOSE FICH1 FICH2 IMPR FPCLIENT.

LECTURE DE FICHIERS SEQUENTIELS – READ

La description du fichier et celle de son enregistrement ont déjà été réalisées dans la DATA DIVISION, de ce fait pour le programme tout se déroule comme si le fichier n’était composé que d’enregistrements logiques qui lui sont délivrés les uns après les autres à chaque ordre de lecture.

Format :
READ nom-de-fichier | INTO nom-donnée | AT END ordre impératif.

Exemple : READ FPCLIEN INTO STRWSS AT END MOVE 1 TOSWFIN.

Remarque : si le fichier est composé d’enregistrements de différentes structures, ils seront délivrés dans la même zone déclarée en FILE SECTION. (pour rappel : redéfinition implicite)

READ InternalFilename [NEXT] RECORD
      [INTO Identifier]
      AT ENDStatementBlock
END-READ

AT END ordre impératif est toujours obligatoire et indique l’opération ou la série d’opération qui doivent être exécutées lorsque la fin du fichier est atteinte.

INTO nom-donnée signifie que le programmeur désire travailler dans une autre zone que celle définie sous le FD du fichier. Soit directement dans une autre structure de fichier soit dans une zone de la Working-storage section. INTO est équivalent à un MOVE de structure à structure.

PERFORM UNTIL StudentRecord = HIGH-VALUES
READ StudentRecords AT END MOVE HIGH-VALUES TO StudentRecord
END-PERFORM.

ECRITURE DE FICHIERS SEQUENTIELS – WRITE

L’instruction WRITE transfère le contenu de la mémoire dans le fichier à la position où l’on se trouve dans le fichier.

Format : WRITE nom-enregistrement [ FROM nom-de-donnée-1 ] .

FROM est équivalent à un MOVE d’une donnée vers la structure d’enregistrement.

Il faut prendre garde au fait que l’on lit un fichier mais que l’on écrit un enregistrement.

FICHIER IMPRIMANTE – WRITE

Format : WRITE nom-enregistrement [ FROM nom-donnée-1 ]

__                                                                                                                          __
| | BEFORE   |    ADVANCING   | nom-de-donnée-2 LINES | |
| | AFTER       |                                      | nombre entier          LINES | |
|                                                                  |                                                          | |
|                                                                  | PAGE                                            | |
L                                                                                                                              J

BEFORE signifie que l’écriture de la ligne sera faite avant le saut de ligne.

AFTER l’écriture sera faite après le saut de ligne.

Le nombre de lignes qu’il faut sauter est donné par la variable nom-de-donnée-2 ou par le nombre entier.

WRITE L80 FROM LIGNE1 AFTER 4.
WRITE L80 FROM LIGNE1 AFTER XLIG.

Nom-de-donnée-2 doit être une zone élémentaire < à 100. La position d’impression est alors avancée de la valeur donnée. Il est conseillé de ne pas mélanger les after et les before.

PAGE signifie que la ligne à imprimer, doit l’être sur la première ligne de la page suivante.

WRITE L80 FROM TITRE AFTER PAGE.

Une bonne organisation du programme consiste à déclarer et définir toutes les lignes d’impression en WORKING-STORAGE SECTION sous la forme suivante :

WORKING-STORAGE SECTION.
01 TITRE PIC X(80) VALUE "CECI EST LE TITRE DE LA PAGE".
01 STITRE PIC X(80) VALUE ALL "_".
01 LIGNE1.
   02 FILLER PIC X(25) VALUE " DATE LIBELLE ".
   02 FILLER PIC X(30) VALUE " DESCRIPTION ".
   02 FILLER PIC XXX VALUE "LE".
   02 JJ PIC 99.
   02 FILLER PIC X VALUE "/".
   02 MM PIC 99.
   02 FILLER PIC X VALUE "/".
   02 ANNEE PIC 9999.
PROCEDURE DIVISION.
DEB.
      ACCEPT MADATE FROM DATE.
      OPEN OUTPUT IMPR.
      WRITE LIMPR FROM TITRE.
      WRITE LIMPR FROM STITRE.
      MOVE JOUR TO JJ
      MOVE MOIS TO MM
      MOVE AN TO ANNEE
      WRITE LIMPR FROM LIGNE1.
      CLOSE IMPR.
      STOP RUN.

Dans le cas d’un fichier de données

    OPEN OUTPUT StudentFile.
    MOVE "9334567Frank Curtain LM051" TO StudentDetails.
    WRITE StudentDetails.
    MOVE "9383715Thomas Healy LM068" TO StudentDetails.
    WRITE StudentDetails.
    CLOSE StudentFile.
    STOP RUN.

STATUS KEY

Il est possible de contrôler le bon achèvement d’une instruction d’entrèe-sortie grâce à un indicateur comportant 2 caractères numériques.
Tout d’abord la clause FILE STATUS is nom-de-donnée dans l’ENVIRONMENT DIVISION au niveau de la clause SELECT doit être définie.
Nom-de-donnée doit être déclaré en WORKING-STORAGE SECTION sous la forme d’un PIC XX. Ensuite l’ordinateur fait le reste, à chaque OPEN – READ – WRITE – CLOSE – …. Il vérifie le bon fonctionnement de l’instruction utilisée et dans ce cas la variable nom-de-donnée est remplie d’un “00” ce qui signifie que l’instruction c’est bien déroulée. Dans le cas contraire il existe dans le manuel du compilateur utilisé une série de code 10 30 34 90 92 96 …. Qui indique le mauvais fonctionnement de l’opération, soit que le fichier n’est pas trouvé, que le EOF est rencontré ou une erreur sur la longueur ou sur la clé etc..

Exemple :

SELECT OPTIONAL FPCLIEN ASSIGN TO DISK
     FILE STATUS IS SKCLIEN.

WORKING-STORAGE SECTION
01 SKCLIEN PIC XX VALUE "00".

PROCEDURE DIVISION.
DEB.
     OPEN INPUT FPCLIEN.
     IF SKCLIEN NOT = "00" PERFORM ERREUROPEN.

L’INSTRUCTION ACCEPT

Le verbe ACCEPT est un verbe particulier de lecture de données à partir de l’écran. On lira toujours des blocs de 80 caractères, même si vous ne devez en lire que 16 par exemple.

Format : ACCEPT nom-de-donnée [ FROM nom-symbolique ]

Le nom-de-donnée représente une zone de donnée en WORKING-STORAGE SECTION dans laquelle seront transmis les octets transmis par le périphérique.

Le nom-symbolique permet de définir un système autre que l’écran pour l’introduction des données.

!!! Attention !!! : cette option est différente selon le compilateur ou l’ordinateur utilisé, référencez-vous auprès de votre manuel utilisateur du Labo

Format spécial de l’instruction ACCEPT

                          | DATE |
ACCEPT nom-de-donnée FROM | DAY  |
                          | TIME |

Ce format permet de transférer dans la zone nom-de-donnée le contenu de l’un de 3 compteurs spéciaux DATE DAY TIME.

DATE est un PIC 9(6) pour AA MM JJ sous la forme 990526

DAY est un PIC 9(5) pour AA JJJ sous la forme 99236

TIME est un PIC 9(8) pour HH MM SS CS

Exemple :

01 DATE-DU-JOUR.
   02 AN   PIC 99.
   02 MOIS PIC 99.
   02 JOUR PIC 99.
PROCEDURE DIVISION.
   ACCEPT DATE-DU-JOUR FROM DATE.

En version 2000
ACCEPT DATE-DU-JOUR FROM CENTURY-DATE
01 DATE-DU-JOUR.
   02 AN   PIC 9999.
   02 MOIS PIC 99.
   02 JOUR PIC 99

Ce verbe correspond à l’émission de données vers l’imprimante ou l’écran.

                | nom-de-donnée-1 | | nom-de-donné-2 |
Format : DISPLAY |                                              |    |                                            | …
                | littéral-1      | | littéral-2     |

               UPON nom-symbolique.

Exemple :
DISPLAY "FIN DU PROGRAMM".
DISPLAY MESSAGE1.

Le nom-symbolique PRINTER indique l’écriture sur l’imprimante.

Le nom-de-donnée peut être une structure.