IFS

43. IFSデータをRPGで読み取るには

前回の「42.EBCDICでないIFSデータをRPGで読み取るには」で
EBCDICではないIFSのストリーム・ファイルを読み取る方法を紹介した。
今回はそのIFSのストリーム・ファイルを読んでDSPFに表示する方法を
紹介する。
_

例: PYTHONソースの表示]

                        PYTHON ソースの表示                                  
                                                                             
プログラム :  WSHOHIN.PTR     ディレトリー  /PYTHON/PROJECT/WSHOHIN          
   1 #*********************************************************#             
   2 #*                                                                      
   3 #*  プログラム名   : WSHOHIN.PY                                         
   4 #*  タイプ         : PYTHON                                             
   5 #*  APP タイプ     : WEB 単票型テンプレート (WSGLCOL)                   
   6 #*  作成日         : 2025/01/29               16:02:09                  
   7 #*  作成者         : QTR                                                
   8 #*  ディレクトリー :  /PYTHON/PROJECT                                   
   9 #*  使用ファイル   : QTRFIL/SHOHIN                                      
  10 #*                   QTRFIL/HINSHU                                      
  11 #*  監査報告書     : Y                                                  
  12 #*  数値の編集     : Y                                                  
  13 #*  画面サイズ                                                          
  14 #*    桁           : 132                                                
  15 #*    行           : 27                                                 
                                                                     続く ...
デバッグ                                                                     
                                                                             
F3= 終了           F6= 停止点の追加 / 消去             F21= コマンド入力     

[解説]

Pythonのソース・プログラムはUtf-8(=CCSID:1208)でIFSに保存されているが
先に説明した方法でオープンして読み取ってやればEBCDAICデータとして
DSPFに表示することができる。
これはその表示結果である。
_

[RPG: DSPPTNSRC ] Pythonソースの読み取りRPG

D LSTAT_          PR            10I 0 EXTPROC('lstat')                                       
D  PATH                           *   VALUE                                                  
D  INFO                           *   VALUE                                                  
                                                                                             
D INFO            DS           128    QUALIFIED                                              
D   ALLOCSIZE                   10U 0 OVERLAY(INFO:45)                      ファイル・サイズ 
   
D TMPBUF          S               *                                         一時バッファー 
D ANS             S              1A                                                        
D TOKENPTR        S               *                                                        
D CRLF            S              3A   INZ(X'0D2500')                                       
D CRLF_P          S               *   INZ(%ADDR(CRLF))                                     
D TMPSRC          S            132A   BASED(TOKENPTR)                                      
  :
C******************************************************     
C     READ          BEGSR                                   
C******************************************************     
C*( データ・ベースの読み取り )                              
 /FREE                                                      
    RES = LSTAT_(%ADDR(PROJECT): INFO_P);// 属性を取得      
    IF (RES = FALSE);  // 失敗                              
      PERROR_(%ADDR(ATTR));                                 
      CLOSE_(FD);                                           
      RETURN;                                               
    ENDIF;             // 失敗                              
    TMPLEN = INFO.ALLOCSIZE;// 割振り長を取得               
    IF ( TMPLEN < 0 ); // メモリー割り振り失敗              
      PERROR_(%ADDR(SUCCESS));                              
      RETURN;                                               
    ELSE;              // メモリー割り振り成功              
      TMPBUF = %ALLOC(TMPLEN);// 動的にメモリを確保         
      BYTE_RED = READ_(FD: TMPBUF: TMPLEN); // READ 読取り  
    ENDIF;             // メモリー割り振り成功              
    CLOSE_(FD);                                             
 /END-FREE                                                  
C*( 読み取ったバッファーを分割する )                      
 /FREE                                                    
    TOKENPTR = STRTOK_(TMPBUF: CRLF_P);                   
    DOW TOKENPTR <> *NULL;                                
      RRN1 = RRN1 + 1;                                    
      IF RRN1 = 23;                                       
        *IN50 = *OFF;                                     
      ENDIF;                                              
      SELECT;                                             
      WHEN  RRN1 >= 1000;                                 
            GYO = %CHAR(RRN1);                            
      WHEN  RRN1 >= 100;                                  
            GYO = ' ' + %CHAR(RRN1);                      
      WHEN  RRN1 >= 10;                                   
            GYO = '  ' + %CHAR(RRN1);                     
      OTHER;                                              
            GYO = '   ' + %CHAR(RRN1);                    
      ENDSL;                                              
      POS = %SCAN(NULL:TMPSRC);                           
      PTNSRC = %SUBST(TMPSRC:1:%SCAN(NULL:TMPSRC) -1);    
   //*-------------------------------------------------// 
      WRITE     SFREC01;   //SFL レコードを追加           
   //*-------------------------------------------------// 
      FLD3 = %SUBST(TMPSRC:POS+1:3);                      
      IF FLD3 = EBC_CRLF; // 次はスペース */        
        RRN1 = RRN1 + 1;                            
        PTNSRC = *BLANKS;                           
        WRITE     SFREC01;   //SFL レコードを追加   
      ENDIF;              // 次はスペース */        
      IF DSPREC = 0;                                
        DSPREC = RRN1;                              
      ENDIF;                                        
      TOKENPTR = STRTOK_(*NULL: CRLF_P);            
    ENDDO;                                          
    IF DSPREC = 0;                                  
      ERR = 'E';                                    
      MSG = ' データの読み取りに失敗しました。 ';   
      EXSR  LRRTN;                                  
    ENDIF;                                          
 /END-FREE                                          
C     REDEND        ENDSR                           

[解説]

ストリーム・ファイルとはファイル全体がひとつの紐のようにつながっている
ファイルのことである。
IBM のDB2/400のようにレコード単位で読み取るのではなく
ファイル全体を一度に読み込まなければならない。
PCに比べてPowerSystemのメモリーが小さくて済んでいるのも
レコード単位での読み取りが可能であるからである。

そこでストリーム・ファイルを読み取るには一般的に次のような
手順が必要になる。
_

①ストリーム・ファイルの属性を入手する。
②ファイルの長さの分だけの動的メモリー・バッファーを
定義して確保する。
③そのメモリー・バッファーにファイルを読み込む
④ファイルをクローズする
⑤メモリー・バッファーを処理する
⑥最後にメモリー・バッファーを解放する

具体的には
①ストリーム・ファイルの属性を入手する。

  RES = LSTAT_(%ADDR(PROJECT): INFO_P);// 属性を取得

  によってファイル・サイズ:ALLOCSIZE を取得する。

②ファイルの長さの分だけの動的メモリー・バッファーを
定義して確保する。

 TMPBUF = %ALLOC(TMPLEN);// 動的にメモリを確保

 によって動的メモリー : TMPBUF を作成して確保する。

③そのメモリー・バッファーにファイルを読み込む

 BYTE_RED = READ_(FD: TMPBUF: TMPLEN); // READ 読取り

 CLOSE_(FD);

⑤メモリー・バッファーを処理する

 ここでいよいよDSPFのSFLレコードに動的メモリーを
分割して書き込む。
ストリーム・ファイルの切れ目(=改行コード)は一般的には
CRLF = 0x0d0a であるがもうすでに EBCDICに変換しているので
切れ目(=改行コード)もEBCDICに変換されており EBCDICの切れ目は
EBC_CRLF = 0x0d25 である。

 TOKENPTR = STRTOK_(TMPBUF: CRLF_P);                   
  DOW TOKENPTR <> *NULL;
   :
   WRITE     SFREC01;   //SFL レコードを追加 
      
   TOKENPTR = STRTOK_(*NULL: CRLF_P);            
  ENDDO; 

この DOWはC言語の典型的な分割方法である。
_

この処理方法のC言語の解説は

53.これは便利な文字列を切り出す strtok (1)

を参照のこと。
今回はILE-RPGでCCSIDのコード変換をしないでもEBCDICで読み取る方法を紹介した。
この方法を使えばC言語がわからないRPGプログラマーでも安心して
IFSストリーム・ファイルを読み取るプログラムを作成できるはずであある。