ツールを作成しているとファイルの CCSID を指定して変換などを行う場合
どうしてもそのファイルの CCSID を取得する必要に迫られてくる。
しかし DSPFD のようなコマンドは存在しないし RTVOBJD では CCSID を
取得することはできない。
データ・ベースの記述を検索する API: QDBRTVFD が提供されているが
これは莫大な情報量を持っていて簡単には扱うことはできない。
一般には API : QDBRTVFD を C 言語や RPG で検索することになるが
( https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_72/apis/qdbrtvfd.htm )
どこにどんな情報が載っているかを調べるだけで相当な時間を要する。
そこでここでは CLP でお手頃に簡単に調べるサンプルを紹介する。
API : QDBRTVFD を使う入り口にでもなれば幸いである。
実行の様子
ファィルの CCSID の検索 (RTVCCSID)
選択項目を入力して,実行キーを押してください。
ファイル . . . . . . . . . . . SHOHIN 名前
ライブラリー . . . . . . . . QTRFIL 文字値
CCSID . . . . . . . . . . 数値
0001.00 CMD PROMPT(' ファィルの CCSID の検索 ')
0002.00 PARM KWD(FILE) TYPE(FILE) +
0003.00 PROMPT(' ファイル ')
0004.00 FILE: QUAL TYPE(*NAME) LEN(10)
0005.00 QUAL TYPE(*CHAR) LEN(10) DFT(*LIBL) +
0006.00 PROMPT(' ライブラリー ')
0007.00 PARM KWD(CCSID) TYPE(*DEC) LEN(5 0) RTNVAL(*YES) +
0008.00 PROMPT(' CCSID ')
CRTCMD CMD(MYLIB/RTVCCSID) PGM(MYLIB/RTVCCSIDCL) SRCFILE(MYSRCLIB/QCMDSRC) ALLOW(*BPGM *IPGM) AUT(*ALL)
0001.00 PGM PARM(&FILFILLIB &CCSID)
0002.00 /*---------------------------------------------------------*/
0003.00 /* RTVCCSID : ファィルの CCSID の検索 */
0004.00 /*---------------------------------------------------------*/
0005.00 DCL VAR(&MSG) TYPE(*CHAR) LEN(132)
0006.00 DCL VAR(&MSGID) TYPE(*CHAR) LEN(7)
0007.00 DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(132)
0008.00 DCL VAR(&MSGF) TYPE(*CHAR) LEN(10) +
0009.00 VALUE('QCPFMSG ')
0010.00 DCL VAR(&MSGFLIB) TYPE(*CHAR) LEN(10) +
0011.00 VALUE('*LIBL ')
0012.00 DCL VAR(&TYPE) TYPE(*CHAR) LEN(1)
0013.00 DCL VAR(&FILFILLIB) TYPE(*CHAR) LEN(20)
0014.00 DCL VAR(&FILE) TYPE(*CHAR) LEN(10)
0015.00 DCL VAR(&FILLIB) TYPE(*CHAR) LEN(10)
0016.00 DCL VAR(&CCSID) TYPE(*DEC) LEN(5 0)
0017.00 DCL VAR(&RCVVAR) TYPE(*CHAR) LEN(512)
0018.00 DCL VAR(&RCVLEN) TYPE(*CHAR) LEN(4)
0019.00 DCL VAR(&CCSID1) TYPE(*DEC) LEN(7 0) /* FILE +
0020.00 CCSID */
0021.00 DCL VAR(&RTNNAM) TYPE(*CHAR) LEN(20) /* RETURNED +
0022.00 FILE NAME */
0023.00 DCL VAR(&APIERR) TYPE(*CHAR) LEN(116) +
0024.00 VALUE(X'000074') /* 2 進数 */
0025.00 DCL VAR(&NULL4) TYPE(*CHAR) LEN(4) +
0026.00 VALUE(X'00000000')
0027.00 MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR))
0028.00
0029.00 RTVJOBA TYPE(&TYPE)
0030.00 CHGVAR VAR(&FILE) VALUE(%SST(&FILFILLIB 01 10))
0031.00 CHGVAR VAR(&FILLIB) VALUE(%SST(&FILFILLIB 11 10))
0032.00 CHGVAR VAR(%BIN(&RCVLEN)) VALUE(512)
0033.00 CALL PGM(QDBRTVFD) PARM(&RCVVAR &RCVLEN &RTNNAM +
0034.00 'FILD0200' &FILFILLIB '*FIRST ' '0' +
0035.00 '*FILETYPE' '*INT' &APIERR)
0036.00 /*( API エラー )*/
0037.00 IF COND(%SST(&APIERR 5 4) *NE &NULL4) THEN(DO)
0038.00 CHGVAR VAR(&MSGID) VALUE(%SST(&APIERR 9 7))
0039.00 CHGVAR VAR(&MSGDTA) VALUE(%SST(&APIERR 17 100))
0040.00 GOTO SNDMSG
0041.00 ENDDO
0042.00 /*( 正常に取得成功 )*/
0043.00 CHGVAR VAR(&CCSID1) VALUE(%BIN(&RCVVAR 46 2))
0044.00 CHGVAR VAR(&CCSID) VALUE(&CCSID1)
0045.00 IF COND(&CCSID *EQ -1) THEN(CHGVAR VAR(&CCSID) +
0046.00 VALUE(65535))
0047.00 RETURN
0048.00
0049.00 ERROR: RCVMSG MSGTYPE(*LAST) RMV(*NO) MSG(&MSG) +
0050.00 MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) +
0051.00 MSGFLIB(&MSGFLIB)
0052.00 SNDMSG:
0053.00 IF COND(&TYPE *EQ '0') THEN(DO)
0054.00 SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +
0055.00 MSGDTA(&MSGDTA) TOMSGQ(*SYSOPR) +
0056.00 MSGTYPE(*COMP)
0057.00 ENDDO
0058.00 ELSE CMD(DO)
0059.00 SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +
0060.00 MSGDTA(&MSGDTA) TOMSGQ(*TOPGMQ) +
0061.00 MSGTYPE(*ESCAPE)
0062.00 ENDDO
0063.00 ENDPGM
CRTCLPGM PGM(MYLIB/RTVCCSIDCL) SRCFILE(MYSRCLIB/QCLSRC) AUT(*ALL)
0033.00 CALL PGM(QDBRTVFD) PARM(&RCVVAR &RCVLEN &RTNNAM + 0034.00 'FILD0200' &FILFILLIB '*FIRST ' '0' + 0035.00 '*FILETYPE' '*INT' &APIERR)
が API: QDBRTVFD を使用している部分である。
受取り変数 &RCVVAR は 512 バイトしか定義していなくてこの変数が
512 バイトしかないことを
0032.00 CHGVAR VAR(%BIN(&RCVLEN)) VALUE(512)
で API に教えている。
QDBRTVFD のすべての情報を戻すには &RCVVAR は 5000 バイトくらいは
必要であるが今回の場合は
0043.00 CHGVAR VAR(&CCSID1) VALUE(%BIN(&RCVVAR 46 2)) 0044.00 CHGVAR VAR(&CCSID) VALUE(&CCSID1)
のようにして CCSID だけを取得するだけなのでこれで十分である。
API は受取り変数の長さに応じた結果だけを戻すように設計されているので
必ずしも全部の長さを定義しておく必要はない。
取得した CCSID が -1 であるとは CCSID= 65535 であることを示している。
0045.00 IF COND(&CCSID *EQ -1) THEN(CHGVAR VAR(&CCSID) + 0046.00 VALUE(65535))
CCSID が 65535 であるというのは CCSID がホワイトの無地の状態で
このファイルがおかれたジョブ環境に染まるという状態である。
参考までにある大手特約店では SE が 5250 エミュレータで Ctrlキー + F3キーで
ジョブの実行 CCSID が変わる?!と教えられたと言っていたがとんでもない間違い。
キー・ボード操作だけでジョブの実行 CCSID が変わるのなら危なくて
しようがない。
これはわかりやすくするためのただの都市伝説である。
もうひとつ CCSID: 1399 はユニコードである、というとんでもない都市伝説を
言ったり個人サイトで公示している人もいるがこれも大きな間違い。
ユニコードの CCSID は UTF-8 が 1208, UTF-16 が 1200 とちゃんと CCSID が
存在していてこの CCSID は全世界のコンピュータに共通であり IBM i だけが
異なる CCSID であることはない。
さらにユニコードの半角は 2バイトで全角は 3バイトである。
( UTF-8 の半角は 1バイト)
IBM i の EBCDIC コードが 1399 になると漢字が突然 3バイトになることは
あり得ない。
CCSID: 1399 はユニコードである、という SE がいたら信用してはいけない。
解説
RTVCCSID は実際は対話式で使用することはない。
バッチで CLP などに組み込んで使って CCSID パラメータ (数字(5,0))にCCSIDの
値が戻される。