RPG

183. 可変長ファイルを扱うには ? (2)

先に紹介した内部記述による可変長ファイルのレコード処理の方法は機能的には
全く問題がないのだが唯一、
バッファー長がメンバー SHOHIN のレコードより大きい
という警告メッセージが出力されてしまうことが問題といえば問題である。
これは 9999 バイトのバッファー長が実際に読み取ったデータ・ベースのレコード長より大きい、
ということが警告メッセージとして出力されているのである。
そこでここに紹介するサンプルは Cランタイム・ライブラリーの

     Ropen, Rclose, Rreadn

という C/400 の関数を使う方法である。
C/400 のために用意されているこれらの関数は、すべてレコード長を指定して読み取ることが
できる機能がある。
従ってファイルをオープンしてからファイルの属性の中からレコード長を取り出して
レコード長を指定して読み取るようにすれば、先の警告メッセージが出力されることはない。
ただし、これらの関数は Cランタイム・ライブラリーの *SRVPGM の公開関数として
定義されているのだが、RPG のための RPG プロトタイプのソースは提供されていない。
C/400 のためのプロトタイプ・ソース : QSYSINC/H(RECIO) のメンバーを見ながら
RPG のソースを作成していたのでは莫大な時間がかかってしまうので
米国で Scott Klement 氏が無償でオープン・ソースとして公開してくれている
RPG 用のプロトタイプ・ソースがあるのでこれを借用することとした。
ただしサンプル・ソースは全くオリジナルとして作成されたものである。

【 サンプル: TESTVAR2 】
-------------------------------------------------------------------------------
0001.00 H DFTNAME(TESTVAR2) DATEDIT(*YMD/) BNDDIR('QC2LE') DFTACTGRP(*NO)      
0002.00 F**********  可変長ファイルの読取り (2) *******************************
0003.00 F*                                                                     
0004.00 F**********************************************************************
0005.00                                                                        
0006.00  /COPY PGMRLIB/QRPGLESRC,RECIO_H                                       
0007.00                                                                        
0008.00 D myFile          DS                  likeds(rfile_t)                  
0009.00 D                                     based(p_myFile)                  
0010.00 D opfb            DS                  likeds(xxopfb_t)                 
0011.00 D                                     based(p_opfb)                    
0012.00 D iofb            DS                  likeds(RIOFB_T)                  
0013.00 D                                     based(p_iofb)                    
0014.00                                                                        
0015.00 D recLen          S             10I 0                                  
0016.00 D Data            S           5000A                                    
0017.00 D dsp40           S             40A                                    
0018.00 D ans             S              1A                                    
0019.00                                                                        
0020.00                                                                        
0021.00  /FREE                                                                 
0022.00    p_myFile = Ropen('QTRFIL/SHOHIN': 'rr');                            
0023.00    p_opfb    = Ropnfbk(myFile);    // オープン・フィードバック域を取得 
0024.00    recLen   = opfb.pgm_Record_len; // レコード長を取得             
0025.00                                                                    
0026.00    dow  *inlr = *OFF;                                              
0027.00      p_iofb = Rreadn(myFile : Data: recLen: r_DFT);                
0028.00      if (iofb.num_bytes = EOF);    // EOF になったら読取り終了     
0029.00         leave;                                                     
0030.00      endif;                                                        
0031.00      dsp40 = Data;                                                 
0032.00      dsply dsp40;                                                  
0033.00    enddo;                                                          
0034.00    Rclose(myFile);                                                 
0035.00    dsply '*EOF' '' ANS;                                            
0036.00                                                                    
0037.00    *inLR = *ON;                                                    
0038.00  /END-FREE                                                         
-------------------------------------------------------------------------------
【 解説 】

Ropen によって任意のファイルをオープンしてファイル識別子 : myFile を取得する。
myFile によってオープン・フィードバック域 obfb を取得してレコード長 recLen を取得する。
レコード長 recLen を指定して

          p_iofb = Rreadn(myFile : Data: recLen: r_DFT);

として Rreadn 関数によって読み取る。
EOF になったら Rclose 関数によってファイルをクローズする。
このように Ropen, Rreadn, Rclose, ... 関数は柔軟で極めてシンプルでもある。
これらの関数は C言語の一般的なものではなく System i だけの上で IBM によって提供されているものである。
他にも Ropen, Rreadn, Rclose, ... の利用方法は数多くあるはずである。

[ 参考 ] RECIO_H