> Tech > RPG ET L’IFS : FICHIERS STREAM BINAIRES

RPG ET L’IFS : FICHIERS STREAM BINAIRES

Tech - Par iTPro.fr - Publié le 24 juin 2010
email

par Scott Klement Mis en ligne le 07/02/2006 - Publié en Juin 2005

Cet article est le quatrième de la série RPG et l’IFS. Le premier article (« Introduction aux fichiers stream », janvier 2005, ou www.itpro.fr Club Abonnés) expliquait les principes de base des fichiers stream – comment les ouvrir et comment les lire et y écrire. Le deuxième article (Fichier texte : une première », mars 2005 ou www.itpro.fr expliquait un style particulier de fichiers stream appelé fichiers texte. Le troisième article (« Fichier texte dans le monde », avril 2005 ou www.itpro.fr ) démontrait quelques utilisations de fichiers texte dans des applications de gestion. Le présent article explique les fichiers stream binaires : des fichiers stream qui contiennent des types de données autres que du texte.Sur l’iSeries, chaque objet disque a un type d’objet particulier, comme *FILE, *PGM, *DTAARA ou *SAVE. Cependant, les plates-formes comme Unix ou Windows n’ont que deux types d’objets disque : fichiers et répertoires. Ces fichiers, appelés fichiers stream, ne servent pas qu’aux données. Ils contiennent aussi des programmes exécutables, des images, du son, de la vidéo et tout ce que l’on peut imaginer d’autre. Les fichiers texte, comme ceux que j’ai présentés dans le précédent article, ne conviennent évidemment pas pour cela. On aura parfois besoin d’un fichier capable de stocker plus que du texte, et c’est là que les fichiers stream binaires ou (« binaires », en abrégé) entrent en scène.

On l’a vu dans le premier article de cette série, les fichiers stream ne sont pas organisés en enregistrements. A leur propos, le système d’exploitation sait seulement qu’ils sont constitués d’un flux continu d’octets. Il vous appartient, en tant que programmeur, de déterminer la manière dont le système interprètera ces octets.

Cette section explique comment organiser un fichier stream en enregistrements et comment extraire ces derniers de manière non séquentielle (c’est-à-dire aléatoire). Quand j’ai présenté ce sujet par le passé, on m’a aussitôt posé la question « : Pourquoi procéder ainsi alors que je peux utiliser un fichier physique normal ? » Une première raison est que vous pourriez être amenés à partager des données avec un programme PC qui ne comprend que les fichiers stream. Mais le principal intérêt d’apprendre ce mécanisme est de mieux comprendre la logique de traitement des données stream.

L e s exemples donnés i c i conviennent particulièrement aux programmeurs RPG – qui pratiquent couramment la lecture et l’écriture d’enregistrements – parce qu’ils utilisent des concepts RPG familiers comme explication. Et même si vous ne devez jamais être amenés à écrire un programme qui écrit des enregistrements dans un fichier stream, le fait de comprendre ces exemples vous permettra de maîtriser la manipulation des données stream pour d’autres tâches.

Pour écrire des données que votre programme peut interpréter comme un enregistrement, chargez-les simplement dans une structure de données et écrivez celle-ci dans le fichier stream. C’est ce qu’illustre le programme de la figure 1. En écrivant deux enregistrements dans le fichier, le programme crée un fichier stream organisé en enregistrements. Le programme commence par créer un nouveau fichier stream (A en figure 1). Les indicateurs passés à l’API open() sont les suivants :

O_WRONLY – Ouvrir le fichier pour l’écriture seule. C’est comme si l’on spécifiait la lettre O en position 17 d’une F-spec.
O_CREAT – Si le fichier n’existe pas, le créer.
O_TRUNC – Si le fichier existe, le tronquer.

Le fait de tronquer le fichier efface toutes ses données, ce qui est analogue à ce que la commande CLRPFM (Clear Physical File Member) fait sur un fichier physique.

Une fois le fichier créé, le programme peuple une structure de données appelée ItemRec avec les données à écrire puis écrit cette structure de données dans le fichier (B en figure 1). Cette structure de données contient des champs packés en plus des caractères texte en EBCDIC. Dans le cas du champ ItemNo, la structure de données contient trois octets qui contiennent les valeurs x’20’, x’00’ et x’1F’ – dont aucun n’est un caractère imprimable, et c’est pourquoi ils sont considérés comme des fichiers stream binaires. Lors de la création d’un fichier tel que celui-ci, il est important de ne pas spécifier les indicateurs O_TEXTDATA ou O_TEXT_ CREAT, parce que ces indicateurs (ou flags) pourraient causer une conversion des données: d’ASCII en EBCDIC ou d’un CCSID (Coded Character Set Identifier) en un autre, ce qui aurait pour effet de changer les valeurs binaires des champs packés.

Une fois le premier enregistrement écrit, le programme en écrit un second (C en figure 1). Rappelons une fois encore qu’il s’agit d’un fichier stream : le système d’exploitation ne sait pas qu’il est constitué d’enregistrements ! Le second enregistrement vient donc se loger sur le disque immédiatement après le premier, adjacent.

Sur l’iSeries, nous sommes habitués à nous déplacer librement dans un fichier. Quand nous travaillons avec un fichier physique ou logique en RPG, un « curseur » suit le numéro d’enregistrement sur lequel le fichier est positionné. Quand on exécute les codes opération SETLL ou SETGT, on change la position de ce curseur afin de pouvoir lire un enregistrement différent. D’où la question, « Comment faire cela avec des fichiers stream ? »

L’API lseek() permet de sauter vers une position particulière du fichier stream. La figure 2 montre le prototype de cette API. La premier paramètre que l’API accepte est filedes (file descriptor), le descripteur de fichier que l’API open() a renvoyé. C’est ainsi que l’API identifie le fichier qu’elle doit traiter. Le deuxième paramètre, offset, est le décalage vers lequel l’API doit déplacer le curseur. Ce décalage est exprimé par un nombre d’octets partant de 0. Le dernier paramètre, whence, indique le point de départ de la recherche dans le fichier – le début du fichier (SEEK_SET), la position courante (SEEK_CUR) ou la fin du fichier (SEEK_END).

Par exemple, pour aller au début du fichier, vous pourriez spécifier 0 octet à partir de SEEK_SET. Pour aller au cinquième octet du fichier, vous spécifieriez 4 octets à partir de SEEK_SET. Pour avancer de 100 octets à partir de la position courante, vous spécifieriez 100 octets à partir de SEEK_CUR. Pour trouver la fin du fichier, vous vous déplaceriez vers 0 octet à partir de SEEK_END.

L’API lseek() utilise un décalage d’octets au lieu d’un numéro d’enregistrement pour définir la position du curseur. D’où la question: Comment l’utiliser pour lire un enregistrement particulier ? Quand les enregistrements de la figure 1 ont été écrits, chacun avait 46 octets de long parce que c’est la taille de la structure de données. Comme les décalages donnés à l’API lseek() partent de 0, les octets 0 à 45 contiennent le premier enregistrement, et les octets 46 à 91 contiennent le deuxième. Donc, si vous utilisez l’API lseek() pour positionner le curseur du fichier en position 0, vous pourriez utiliser l’API read() pour obtenir le premier enregistrement. De la même manière, si vous ordonnez à lseek() de déplacer le curseur en position 46 du fichier, vous pouvez lire le deuxième enregistrement. S’il y en avait un troisième, vous pourriez le lire à partir de la position 92.

C’est ce qu’illustre le code de la figure 3. Il soustrait un du numéro d’enregistrement et le multiplie par la longueur d’enregistrement (A en figure 3). Le code utilise ensuite lseek() pour sauter à cette position et lire l’enregistrement (B en figure 3). Quand le code de la figure 3 a fini de s’exécuter, les données du deuxième enregistrement sont chargées dans la structure de données.

L’exemple de la figure 1 montre comment créer un fichier vide et y écrire deux enregistrements. Si vous préférez prendre un fichier existant et ajouter les enregistrements à la fin, vous pouvez utiliser l’indicateur O_APPEND. Avec cet indicateur, les données seront toujours écrites à la fin du fichier. La figure 4 utilise cette méthode pour ajouter un troisième enregistrement au fichier.

Si l’on ne spécifie pas O_APPEND, les données sont écrites à la position où se trouve le curseur du fichier. Si vous utilisez lseek() pour vous positionner au début du fichier puis écrire un enregistrement, celui-ci remplace les éventuelles données qui se trouvaient là. C’est ainsi que l’on fait une mise à jour sur un fichier stream. De la même manière, vous pouvez utiliser lseek() pour sauter à la fin du fichier et y ajouter les données, tout comme elles le seraient si vous aviez spécifié l’indicateur O_APPEND. De sorte que vous pouvez utiliser le même appel pour ouvrir (open()) pour lire, écrire et mettre à jour.

C’est ce que montre le code de la figure 5. L’indicateur O_RDWR ouvre le fichier pour la lecture et l’écriture (A en figure 5). Puis, le code lit le deuxième enregistrement du fichier, change le nom du widget et met à jour l’enregistrement (B en figure 5). Il ajoute ensuite un quatrième enregistrement au fichier (C en figure 5).

Téléchargez gratuitement cette ressource

Guide de Services Cloud Managés

Guide de Services Cloud Managés

Accélérer votre transformation digitale, protéger et sécuriser vos environnements Cloud avec les offres de support, d'accompagnement et de services managés. Découvrez le TOP 3 des Services Managés pour accompagner la transformation de vos environnements Cloud, gagner en agilité et en sécurité dans un monde d'incertitudes.

Tech - Par iTPro.fr - Publié le 24 juin 2010