%EOF
Détecter la fin de fichier
Renvoie *ON quand la dernière lecture n'a plus rien trouvé à lire, c'est-à-dire en fin de fichier ou, avec READE, à la fin de la clé demandée.
Syntaxe
%EOF(nom-fichier)
%EOF
nom-fichier- Le fichier dont on veut l'état. Il peut être omis, mais dès qu'un programme manipule plusieurs fichiers, mieux vaut toujours le nommer.
- Résultat
- Un indicateur (*ON ou *OFF). *ON après une lecture qui a échoué faute d'enregistrement ; *OFF sinon.
À quoi ça sert
Toute boucle de lecture en RPG full free repose sur %EOF : on lit un premier enregistrement, on boucle tant que la lecture a réussi, et on relit à la fin de chaque tour. Plus besoin d'indicateur numéroté en colonne 75.
La fonction sert aussi avec READE : quand la clé change, la lecture s'arrête et %EOF passe à 1, comme si le fichier était fini. C'est ce qui permet de parcourir « tous les clients de Lyon » sans se soucier de ce qui suit dans l'index.
Exemple 1 : Boucle de lecture classique
**free
// %EOF : parcourir un fichier jusqu'a la fin.
ctl-opt dftactgrp(*no) actgrp(*new) alwnull(*usrctl);
dcl-f client keyed;
dcl-s nb int(5) inz(0);
dcl-s total packed(11:2) inz(0);
read client;
dow not %eof(client);
nb += 1;
total += solde;
snd-msg 'Client ' + %char(numcli) + ' : ' + %trim(nom);
read client;
enddo;
snd-msg 'Lignes lues : ' + %char(nb) + ' - solde cumule : ' + %char(total);
snd-msg 'Derniere valeur de NUMCLI : ' + %char(numcli);
snd-msg '%EOF apres la boucle : [' + %char(%eof(client)) + ']';
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Client 100 : Dupont SA
Client 200 : Martin et fils
Client 300 : Leroy SARL
Client 400 : Bernard Transports
Client 500 : Petit Atelier
Lignes lues : 5 - solde cumule : 98975.60
Derniere valeur de NUMCLI : 500
%EOF apres la boucle : [1]
Le premier READ est fait avant la boucle, le suivant à la fin de chaque tour. Le test dow not %eof arrête donc la boucle dès que la lecture a échoué, sans traiter deux fois le dernier client. Après la fin de fichier, les zones du format gardent leur dernière valeur (NUMCLI vaut toujours 500).
Exemple 2 : Avec READE : la fin de la clé
**free
// %EOF avec READE : la fin de la cle compte comme une fin de fichier.
ctl-opt dftactgrp(*no) actgrp(*new) alwnull(*usrctl);
dcl-f clientv keyed;
dcl-ds lg likerec(clientvr : *input);
// Clients de Lyon : READE s'arrete quand la ville change, pas a la fin du fichier
setll ('Lyon') clientvr;
reade ('Lyon') clientvr lg;
dow not %eof(clientv);
snd-msg 'Lyon : ' + %trim(lg.nom);
reade ('Lyon') clientvr lg;
enddo;
snd-msg 'Fin de la boucle : %EOF = [' + %char(%eof(clientv)) + ']';
// Brest n'a qu'un client : le 2e READE echoue alors que le fichier continue apres
setll ('Brest') clientvr;
reade ('Brest') clientvr lg;
snd-msg 'READE 1 Brest : ' + %trim(lg.nom) + ', %EOF = [' + %char(%eof(clientv)) + ']';
reade ('Brest') clientvr lg;
snd-msg 'READE 2 Brest : %EOF = [' + %char(%eof(clientv)) + ']';
// Une ville qui n'existe pas : SETLL ne signale rien, c'est le READE qui echoue
setll ('Paris') clientvr;
snd-msg 'SETLL Paris : %EOF = [' + %char(%eof(clientv)) + ']';
reade ('Paris') clientvr lg;
snd-msg 'READE Paris : %EOF = [' + %char(%eof(clientv)) + ']';
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Lyon : Martin et fils
Lyon : Petit Atelier
Fin de la boucle : %EOF = [1]
READE 1 Brest : Bernard Transports, %EOF = [0]
READE 2 Brest : %EOF = [1]
SETLL Paris : %EOF = [0]
READE Paris : %EOF = [1]
Lyon compte deux clients : le troisième READE échoue et %EOF vaut 1 alors que le fichier contient encore d'autres villes. Brest n'a qu'un client : le premier READE réussit (%EOF à 0), le second échoue. Pour une ville absente comme Paris, SETLL ne signale rien : c'est le READE qui met %EOF à 1.
Exemple 3 : Quand %EOF change (et quand il ne change pas)
**free
// %EOF garde sa valeur tant qu'une operation ne la remet pas a jour.
ctl-opt dftactgrp(*no) actgrp(*new) alwnull(*usrctl);
dcl-f client keyed;
// On lit jusqu'a la fin : %EOF passe a 1
setll *loval client;
dou %eof(client);
read client;
enddo;
snd-msg 'Fin de fichier : %EOF = [' + %char(%eof(client)) + ']';
// CHAIN qui echoue : %EOF reste a 1 (valeur perimee)
chain (999) client;
snd-msg 'CHAIN 999 (absent) : %EOF = [' + %char(%eof(client)) +
'] %FOUND = [' + %char(%found(client)) + ']';
// CHAIN qui reussit : %EOF repasse a 0
chain (100) client;
snd-msg 'CHAIN 100 (trouve) : %EOF = [' + %char(%eof(client)) +
'] %FOUND = [' + %char(%found(client)) + ']';
// SETLL au-dela du dernier enregistrement : rien sur %EOF, le READE suivant l'allume
setll (999) client;
snd-msg 'SETLL 999 : %EOF = [' + %char(%eof(client)) + ']';
read client;
snd-msg 'READ apres SETLL : %EOF = [' + %char(%eof(client)) + ']';
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Fin de fichier : %EOF = [1]
CHAIN 999 (absent) : %EOF = [1] %FOUND = [0]
CHAIN 100 (trouve) : %EOF = [0] %FOUND = [1]
SETLL 999 : %EOF = [0]
READ apres SETLL : %EOF = [1]
Après une lecture jusqu'à la fin, %EOF vaut 1. Un CHAIN qui échoue le laisse à 1 : la valeur est périmée. Un CHAIN qui réussit le remet à 0. Un SETLL au-delà de la dernière clé n'y touche pas non plus ; c'est le READ suivant qui l'allume.
Le piège
Ne pas relire %EOF après un CHAIN qui échoue. Dans le troisième exemple, après chain (999), %EOF vaut encore 1 alors que le CHAIN n'a rien à voir avec une fin de fichier. Pour savoir si un CHAIN a trouvé l'enregistrement, on interroge %FOUND, jamais %EOF.
Deuxième point vérifié : après un SETLL à une clé qui n'existe pas (999), %EOF reste à 0. La fin de fichier n'est signalée que par la lecture suivante.