Apprendre Cobol – Les bases

Mise à jour d’un fichier LINE SEQUENTIAL sous OpenCobolIDE

Dans beaucoup de cours, on voit la combinaison OPEN I-O, REWRITE et DELETE pour modifier ou supprimer un enregistrement. Le problème est que, sous OpenCobolIDE (et donc GnuCOBOL), cette approche n’est pas autorisée quand le fichier est déclaré en ORGANIZATION IS LINE SEQUENTIAL.

Pourquoi ça échoue :
Un fichier LINE SEQUENTIAL est un fichier texte “ligne par ligne”. Comme les lignes peuvent être écrites avec des longueurs physiques variables (fin de ligne, traitements des espaces, etc.), le compilateur refuse la mise à jour “sur place”. Résultat : erreurs de compilation du type OPEN I-O not allowed et DELETE not allowed.

Objectif du cours

L’objectif reste le même : parcourir un fichier de notes, proposer une action sur chaque ligne (modifier, supprimer, conserver), puis obtenir un fichier final mis à jour. La différence est la méthode : pour un fichier texte LINE SEQUENTIAL, on fait une mise à jour par recopie.

Ce que vous aviez tenté (et pourquoi ce n’est pas adapté)

Le code ci-dessous ressemble à une approche “mise à jour directe”. Sous OpenCobolIDE, il déclenche les erreurs mentionnées, car il mélange LINE SEQUENTIAL avec OPEN I-O et DELETE.


IDENTIFICATION DIVISION.
PROGRAM-ID. MISE-A-JOUR-FICHIER.

ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
    SELECT FICHIER-NOTES ASSIGN TO "notes.txt"
           ORGANIZATION IS LINE SEQUENTIAL.

DATA DIVISION.
FILE SECTION.
FD  FICHIER-NOTES.
01  ENREGISTREMENT-NOTE.
    05  NUMERO-ETUDIANT   PIC 9(5).
    05  NOM               PIC X(20).
    05  NOTE              PIC 9(2)V9.

WORKING-STORAGE SECTION.
01  FIN-FICHIER           PIC X       VALUE "N".
01  CHOIX                 PIC X.
01  NOUVELLE-NOTE         PIC 9(2)V9.

PROCEDURE DIVISION.
    OPEN I-O FICHIER-NOTES.

    PERFORM TRAITER-ENREGISTREMENT UNTIL FIN-FICHIER = "O".

    CLOSE FICHIER-NOTES.
    DISPLAY "Mise à jour terminée.".
    STOP RUN.

TRAITER-ENREGISTREMENT.
    READ FICHIER-NOTES
        AT END
            MOVE "O" TO FIN-FICHIER
        NOT AT END
            DISPLAY "Action ? ..."
            ACCEPT CHOIX
            EVALUATE TRUE
                WHEN CHOIX = "M"
                    ACCEPT NOUVELLE-NOTE
                    MOVE NOUVELLE-NOTE TO NOTE
                    REWRITE ENREGISTREMENT-NOTE
                WHEN CHOIX = "S"
                    DELETE FICHIER-NOTES
            END-EVALUATE
    END-READ.

La méthode compatible : recopie dans un fichier temporaire

La mise à jour d’un fichier texte se fait en 5 étapes très simples :

Avantage pédagogique :
Cette technique marche partout pour les fichiers texte. Elle reflète aussi une réalité terrain : de nombreux traitements “batch” historiques mettent à jour des fichiers séquentiels par reconstruction.

Code corrigé (compatible OpenCobolIDE)

Dans cet exemple, la note est stockée en texte PIC X(4) pour être cohérente avec un fichier lisible comme 12.5, 08.0. Si vous voulez un format purement numérique (implied decimal), il faut alors stocker les notes sans point (ex. 125 pour 12,5), ce qui rend le fichier moins lisible.


IDENTIFICATION DIVISION.
PROGRAM-ID. MISE-A-JOUR-FICHIER-TEXTE.

ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
    SELECT FICHIER-IN  ASSIGN TO "notes.txt"
           ORGANIZATION IS LINE SEQUENTIAL.
    SELECT FICHIER-OUT ASSIGN TO "notes.tmp"
           ORGANIZATION IS LINE SEQUENTIAL.

DATA DIVISION.
FILE SECTION.

FD  FICHIER-IN.
01  ENREG-IN.
    05  NUMERO-ETUDIANT-IN  PIC 9(5).
    05  NOM-IN              PIC X(20).
    05  NOTE-IN             PIC X(4).

FD  FICHIER-OUT.
01  ENREG-OUT.
    05  NUMERO-ETUDIANT-OUT PIC 9(5).
    05  NOM-OUT             PIC X(20).
    05  NOTE-OUT            PIC X(4).

WORKING-STORAGE SECTION.
01  FIN-FICHIER     PIC X VALUE "N".
01  CHOIX           PIC X VALUE SPACE.
01  NOUVELLE-NOTE   PIC X(4) VALUE SPACES.

PROCEDURE DIVISION.
    OPEN INPUT  FICHIER-IN
    OPEN OUTPUT FICHIER-OUT

    PERFORM UNTIL FIN-FICHIER = "O"
        READ FICHIER-IN
            AT END
                MOVE "O" TO FIN-FICHIER
            NOT AT END
                DISPLAY SPACE
                DISPLAY "Étudiant : " NUMERO-ETUDIANT-IN " " NOM-IN " - Note : " NOTE-IN
                DISPLAY "Action ? (M=modifier, S=supprimer, Entrée=passer) : "
                ACCEPT CHOIX

                EVALUATE TRUE
                    WHEN CHOIX = "M" OR CHOIX = "m"
                        DISPLAY "Nouvelle note (ex: 16.0) : "
                        ACCEPT NOUVELLE-NOTE

                        MOVE NUMERO-ETUDIANT-IN TO NUMERO-ETUDIANT-OUT
                        MOVE NOM-IN             TO NOM-OUT
                        MOVE NOUVELLE-NOTE      TO NOTE-OUT
                        WRITE ENREG-OUT

                        DISPLAY "Note modifiée (écrite dans notes.tmp)."

                    WHEN CHOIX = "S" OR CHOIX = "s"
                        DISPLAY "Enregistrement supprimé (non recopié)."

                    WHEN OTHER
                        MOVE NUMERO-ETUDIANT-IN TO NUMERO-ETUDIANT-OUT
                        MOVE NOM-IN             TO NOM-OUT
                        MOVE NOTE-IN            TO NOTE-OUT
                        WRITE ENREG-OUT

                        DISPLAY "Enregistrement conservé (recopié)."
                END-EVALUATE
        END-READ
    END-PERFORM

    CLOSE FICHIER-IN
    CLOSE FICHIER-OUT

    DISPLAY "Traitement terminé."
    DISPLAY "Renommez notes.tmp en notes.txt (ou remplacez notes.txt par notes.tmp)."
    STOP RUN.
Copier le code

Exemple de fichier notes.txt avant exécution

Chaque ligne correspond à un enregistrement de longueur fixe : 9(5) pour le numéro (5 chiffres), X(20) pour le nom (rempli avec des espaces), et X(4) pour la note (ex. 08.0).


00001DUPONT     Jean           12.5
00002MARTIN     Sophie         08.0
00003BERNARD    Lucas          15.5
00004DURAND     Emma           09.0

Exemple de résultat (fichier temporaire notes.tmp)

Si vous modifiez l’étudiant 00001 en 16.0 et si vous “supprimez” 00002 (donc vous ne le recopiez pas), le fichier temporaire contiendra :


00001DUPONT     Jean           16.0
00003BERNARD    Lucas          15.5
00004DURAND     Emma           09.0

Explications détaillées

1) Deux fichiers au lieu d’un seul

2) Modifier une ligne

Quand l’utilisateur choisit M, on lit la nouvelle note, puis on écrit dans le fichier temporaire une ligne identique, sauf la note remplacée. Ici, on utilise WRITE, jamais REWRITE.

3) Supprimer une ligne

Pour “supprimer” un enregistrement dans un fichier texte, on ne peut pas retirer une ligne au milieu du fichier. La suppression se fait donc par une règle simple : ne pas écrire la ligne dans le fichier temporaire. Il n’y a donc pas de DELETE dans cet exemple.

4) Conserver une ligne

Si l’utilisateur ne fait rien (Entrée) ou choisit une autre touche, on recopie la ligne telle quelle dans le fichier temporaire.

Conseil pour vos pages de cours :
Si vous souhaitez enseigner OPEN I-O, REWRITE et DELETE, faites-le dans un chapitre “fichiers indexés” (ORGANIZATION IS INDEXED) ou “fichiers relatifs”. Sur LINE SEQUENTIAL, la méthode fiable est la recopie.

Résumé à retenir