IFS

33. IFSストリーム・ファイルをEBCDICで読み取るRPG

IFSストリーム・ファイルは一般的にはCCSID:819または943つまり
ASCIIコードで書かれている。
IFSを扱うのに苦手意識があるのはIFSストリーム・ファイルの大半が
ASCIIコードで書かれているからではないだろうか?
RPGで扱うときには読取った内容を調べるには
EBCDICに変換して調べなければならないからである。
先に紹介した「32.RPGでIFSファイルをオープンする」でも
API: QDCXLATE を使ってASCIIからEBCDICへとコード変換を行っていたが
これはやはり面倒であるし手間もかかる。
もっと良い方法はないものだろうか?
今回はそれを進化させた良い方法を紹介しよう。

実はIFSストリーム・ファイルをEBCDICとして読取る方法が用意されている。

C言語のopen関数でオプションをうまく指定すれば
読取った結果をEBCDICとすることができるのである。
つまりIFSファイルを読取ればもうEBCDICに変わっているという方法である。
ええそんな方法があるの?!と驚くのも無理はない。
では、ここでその便利な方法を紹介しよう。

[ IFSをEBCDICで読みとるRPG: TESTREAD3 ]

ソースはこちらから

0001.00 H DFTNAME(TESTREAD3) DATEDIT(*YMD/)                                      
0002.00 H CCSID(*GRAPH:*SRC)                                                     
0003.00 F********** IFS ストリーム F を EBCDIC として読取る *******************  
0004.00 F*                                                                       
0005.00 F**********************************************************************  
0006.00                                                                          
0007.00  * CRTBNDRPG  OBJ(OBJLIB/TESTREAD3) SRCFILE(MYSRCLIB/QRPGLESRC)          
0008.00  * DFTACTRP(*NO) ACTGRP(*NEW) DBGVIEW(*SOURCE) AUT(*ALL)                 
0009.00                                                                          
0010.00  *-------------------------------------------------------------------*   
0011.00  *  2021/12/01 : 作成                                                    
0012.00  *-------------------------------------------------------------------*   
0013.00  /COPY QSYSINC/QRPGLESRC,IFS                                             
0014.00  *( 作業変数 )                                                           
0015.00 D FILE            S            128A   INZ('/AS400-NET.USR/TEMP/TEST.XML')
0016.00 D STAT_           DS                  LIKEDS(stat_t)                     
0017.00 D TRUE#           S              4B 0 INZ(0)                             
0018.00 D FALSE#          S              4B 0 INZ(-1)                            
0019.00 D FD              S             10I 0                                    
0020.00 D TMPBUF          S               *                                      
0021.00 D TMPLEN          S             10I 0                                    
0022.00 D BYTE_RED        S             10I 0                                    
0023.00 D CCS5035         S             10I 0 INZ(5035)                          
0017.00 D TRUE#           S              4B 0 INZ(0)                                   
0018.00 D FALSE#          S              4B 0 INZ(-1)                                  
0019.00 D FD              S             10I 0                                          
0020.00 D TMPBUF          S               *                                            
0021.00 D TMPLEN          S             10I 0                                          
0022.00 D BYTE_RED        S             10I 0                                          
0023.00 D CCS5035         S             10I 0 INZ(5035)                                
0024.00 D MSG             S             80A                                            
0025.00                                                                                
0026.00  /FREE                                                                         
0027.00     FD = open(%TRIM(FILE): O_RDONLY + O_TEXTDATA + O_CCSID:0:CCS5035);         
0028.00     IF FD = FALSE#;                                                            
0029.00       MSG = ' ファイル ' + %TRIMR(FILE) + ' のオープンに失敗しました。 ';      
0030.00       RETURN;                                                                  
0031.00     ENDIF;                                                                     
0032.00     lstat(%TRIM(FILE): STAT_);                                                 
0033.00     TMPLEN   = STAT_.st_size;                                                  
0034.00     TMPBUF   = %ALLOC(TMPLEN);                                                 
0035.00     BYTE_RED = read (FD: TMPBUF: TMPLEN);                                      
0036.00     CALLP close(FD);                                                           
0037.00     DEALLOC TMPBUF;                                                            
0038.00  /END-FREE                                                                     
0039.00 C                   SETON                                        LR            
0040.00 C                   RETURN                                                


      

[コンパイル]

CRTBNDRPG PGM(TEST.COM/TESTREAD3) SRCFILE(R610SRC/QRPGLESRC) DFTACTGRP(*NO)
ACTGRP(*NEW) DBGVIEW(*SOURCE) AUT(*ALL)

[解説]

0027.00     FD = open(%TRIM(FILE): O_RDONLY + O_TEXTDATA + O_CCSID:0:CCS5035);

で指定しているのは第1パラメータは %TRIM(FILE) としてファイル名に続いて
第2パラメータとして O_TEXTDATA + O_CCSID を指定すれば変換CCSIDを
指定することができる。
そして第4パラメータとして実際に変換したい先のCCSIDを指定すると
ファイルのCCSIDから指定した変換先のCCSIDとファイルの内容が置換えられる。

0032.00     lstat(%TRIM(FILE): STAT_);

でファイルの属性を読取ってから

0033.00     TMPLEN   = STAT_.st_size;                                                  
0034.00     TMPBUF   = %ALLOC(TMPLEN);                                                 
0035.00     BYTE_RED = read (FD: TMPBUF: TMPLEN); 

のようにしてサイズを取得してそのサイズの分だけ動的に変数の長さを
割振って read で変数 TMPBUF の中にIFSストリーム・ファイルの内容を
書き込むのである。
この処理によってIFSには ASCIIで書かれていてもRPGプログラムの中では
EBCDICとして読取ることができる。

RPGプログラマーとしては非常に安心できる方法であるので
ぜひ覚えておいて頂きたい。
読んでてよかったAS400 Tips & Techniques である。