読者です 読者をやめる 読者になる 読者になる

きどたかのブログ

いつか誰かがこのブログからトラブルを解決しますように。

ibm.swapLFについて<続々>

z/OS Java WebSphere Application Server 文字コード EBCDIC

ibm.swapLFにかかりきり。

 

System.outに使われるクラスが、

WAS for z/OSでは普通のプラットフォームとは違うクラスであることが分かった。

USSでWAS付属のjava叩いても、WAS上とは違いがでる。

com.ibm.ws390.SystemOutErrCodepageというプロパティがあることが判明。

ibm.swapLF使うよりもこっちを使う方が影響範囲が狭まるので良いと思う。

 

まあ、そのへんはいいか。

今書きたいのは小さいバグを見つけた話。

IBM1047_LFを使ってデコードする方法によっては、

お前さんLFをスワップしてねーじゃないかというバグを見つけた。

ibm.swapLFはつけてない。

IBM1047_LFというコードページの機能であるはずです。

 

今回3種類試してみて、やはりよく使われる方法だけが想定外の動きをする。

1. new String(byte bytes, String charset) コイツが壊れてる!

2. new String(byte bytes, Charset charset)

3. Charset.forName(String charset).decode(ByteBuffer buf)

(2と3はたいした違いは無いってツッコミはしてもいい)

 

今回の入力データとして用いたEBCDICなデータはこちらです。

new byte { (byte) -127, 0x15, (byte) -127, 0x0d, 0x25, (byte) -127 };

制御記号とかです。

"a"(0x81)を作るのに(byte)-127とかしてます。申し訳ない汚くて。

 

テストは簡単。

byteからStringを作る もしくは CharBufferを作る。

byteがどのcharにマッピングされたかを確認する。

ついでに逆方向も試す。

StringからgetBytes(String charset)でbyteに戻す 

もしくは encode(CharBuffer buf)でByteBufferに戻す。

 

結果はご覧のとおりです

new String(byte bytes,String charset)
8115810d2581
610a610d8561
8125810d1581
new String(byte bytes,Charset charset)
8115810d2581
6185610d0a61
8115810d2581
charset.decode(ByteBuffer buf)
8115810d2581
6185610d0a61
8115810d2581

 

デコード前データ bytes(EBCDIC) みんな同じです

デコード後データ chars

エンコード後データ bytes(EBCDIC)

 

ふむ、これはきっとこいつがバグってるんだな。

sun.io.ByteToCharCp1047_LF

公開してないクラスのバグを指摘したいわけじゃないが、

こいつのマッピングが間違ってそうなのも家で実験した。

new sun.io.ByteToCharCp1047().convertAll(byte bytes)
8115810d2581
610a610d8561
8115810d2581
new sun.io.ByteToCharCp1047_LF().convertAll(byte[] bytes)
8115810d2581
610a610d8561 LF付いてないクラスと同じ結果だと!?
8125810d1581

おいおい、末尾にLF付いてる由縁はcharをbyteにする時だけか?

(charをbyteにするのはsun.io.CharToByteCp1047_LFを使用してます)

 

nioとの一貫性がないため、これはバグと呼んでいいはずだ。

あとibm.swapLFはきっとbyteを置換する機能なんじゃないかと考えてる。

charとbyteの相互変換の際に作用するものじゃないって予想。