好むと好まざるにかかわらず RPG で Unicode を扱う必要がある時代はすぐそこにやってきている。
今から少しずつでも Unicode に馴染んでおきたいものである。
RPG で Unicode ( UTF-8 ) のストリーム・ファイルを IFS に出力するにはどのようにすればよいのだろうか ?
RPG で IFS へ Unicode ファイルを出力するサンプルを紹介しよう。
------------------------------------------------------------------------------------ 0001.00 H DFTNAME(TESTUNI) DATEDIT(*YMD/) BNDDIR('QC2LE') 0002.00 F******** IFS への UNICODE 出力 *************************************** 0003.00 F* 0004.00 F* CRTRPGMOD QTEMP/TESTUNI SRCFILE(PGMRLIB/QRPGLESRC) AUT(*ALL) 0005.00 F* CRTPGM OBJLIB/TESTUNI MODULE(QTEMP/TESTUNI) 0006.00 F* SRVPGM(QSYS/QP0LLIB1) AUT(*ALL) 0007.00 F* 0008.00 F********************************************************************** 0009.00 D FD S 10I 0 0010.00 D DATA S 1000C CCSID(1200) 0011.00 0012.00 D OPEN_ PR 10I 0 EXTPROC('open') 0013.00 D PATH * VALUE 0014.00 D FLAG 10I 0 VALUE 0015.00 D MODE 10I 0 VALUE OPTIONS(*NOPASS) 0016.00 D CODEPAGE 10I 0 VALUE OPTIONS(*NOPASS) 0017.00 D TOPAGE 10I 0 VALUE OPTIONS(*NOPASS) 0018.00 0019.00 D WRITE_ PR 10I 0 EXTPROC('write') 0020.00 D DESC 10I 0 VALUE 0021.00 D DATA * VALUE 0022.00 D DTALEN 10I 0 VALUE 0023.00 0024.00 D CLOSE_ PR EXTPROC('close') 0025.00 D DESC 10I 0 VALUE 0026.00 0027.00 D PERROR_ PR EXTPROC('perror') 0028.00 D STR * VALUE 0029.00 0030.00 D O_CREAT S 10I 0 INZ(8) 0031.00 D O_TRUNC S 10I 0 INZ(64) 0032.00 D O_CCSID S 10I 0 INZ(32) 0033.00 D O_WRONLY S 10I 0 INZ(2) 0034.00 D S_IWUSR S 10I 0 INZ(128) 0035.00 D S_IRUSR S 10I 0 INZ(256) 0036.00 D PATH S 14A INZ('/A001/TEST.TXT') 0037.00 D MSG S 80A INZ(' オープン・エラーです ') 0038.00 0039.00 /FREE 0040.00 FD = OPEN_(%ADDR(PATH): 0041.00 O_CREAT + O_TRUNC + O_CCSID + O_WRONLY : 0042.00 S_IWUSR + S_IRUSR : 0043.00 1208); 0044.00 IF (FD < 0); 0045.00 PERROR_(%ADDR(MSG)); 0046.00 RETURN; 0047.00 ENDIF; 0048.00 DATA = %UCS2('hello UNICODE'); 0049.00 WRITE_(FD : %ADDR(DATA) : %LEN(%TRIMR(DATA)) * 2); 0050.00 CLOSE_(FD); 0051.00 *INLR = *ON; 0052.00 /END-FREE ------------------------------------------------------------------------------------
CRTRPGMOD QTEMP/TESTUNI SRCFILE(PGMRLIB/QRPGLESRC) AUT(*ALL) CRTPGM OBJLIB/TESTUNI MODULE(QTEMP/TESTUNI) SRVPGM(QSYS/QP0LLIB1) AUT(*ALL)
のようにして QSYS/QP0LLIB1 *SRVPGM
をバインドしてビルドする必要がある。
QSYS/QP0LLIB1
とは open
, read
, write
, close
等の IFS API
が保管されている
サービス・プログラムである。これらの関数は C/400 の関数( QC2LE
) ではないので
BNDDIR('QC2LE')
には含まれていない。従って明示的にバインドしてやる必要がある。
米国雑誌でも IFS の入出力を RPG で行う方法のサンプル・ソースはよく紹介されているが
いずれも ある公開ライブラリーをダウンロードして導入しなければならない。
上記のように、どのような System i でも 動作する IFS への入出力の事例を示しているのは
珍しいはずである。(もちろん IBM マニュアルには掲載されていない。)
上記の例では IFS の入出力の open
, write
, close
を使っている以外として Unicode に係わる部分は
0010.00 D DATA S 1000C CCSID(1200) 0040.00 FD = OPEN_(%ADDR(PATH): 0041.00 O_CREAT + O_TRUNC + O_CCSID + O_WRONLY : 0042.00 S_IWUSR + S_IRUSR : 0043.00 1208); 0048.00 DATA = %UCS2('hello UNICODE');
の行だけである。
最初に DATA
という 1000バイトのフィールドの定義で 1000C
の C
は、この DATA
が
UCS-2 ( CCSID 13488 )
であることを宣言している。
CCSID(1200)
は UTF-16 という意味である。( UTF-8 つまり CCSID(1208)
を定義することはできない。)
次に CCSID = 1208 (UTF-8)
を無理やり指定して ( UTF-16 であれば 1200 ) O_CCSID
を
オプション指定することによって open
関数を実行している。
これによって WRKLNK
で作成された IFS ストリーム・ファイルの属性を調べれば
CCSID は 1208 つまり UTF-8 となっているはずである。
さらに
DATA = %UCS2('hello UNICODE');
によって 'hello UNICODE
' という文字列を UTF-16 に置き換えている。
%UCS2
とは IBM によって RPG 上で提供されている Unicode 変換のための BIFF
関数である。
この TESTUNI
というプログラムを実行してみると IFS には
h e l l o U N I C O D E
という文字列が UTF-16 として出力されてるのを確認することができる。
半角で入力したはずの英小文字も倍角となっているのだから、これは UTF-16 である。
ところで %UCS2
は日本語漢字も UTF-16 に変換できるのだろうか ?
試してみたところ文字化けして全くダメであった。
また RPG は UTF-8 への変換をサポートする機能はあるのだろうか ?
これも %USC2
は UCS-2 ( CCSID 13488 )
だけへの変換であり、 UTF-8 への変換は
全くサポートされていない。
現実では Uncode は UTF-8 による使用が全世界で圧倒的多数を占めている。
IBM の対応は遅れている感が否めない。
EnterpriseServer では UNI_CODE *SRVPGM
をユーザーに提供して UTF-8
, EBCDIC
, ASCII
の相互変換をサポートしている。