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

CCSID930(CP930)をUTF-8へエンコードする

CCSID 930という文字コードについて少し調べてみました。

CCSID 930

CCSID 930はIBM漢字コードの一つでEBCDICがベースになっています。
1byteの半角文字と2byteの日本語で構成されています。
CCSID 930はCCSID 5026のスーパーセットで、1byteはCCSID 290、2byteはCCSID 300の
文字コードを切り替えて使用しているようです。

CCSID 930のコード表は下記で公開されています。
(Code page 00290と00300のリンク)
http://www-01.ibm.com/software/globalization/ccsid/ccsid930.html

シフトコード

どうやら調べてみると、CCSID 930では2byteの文字はシフトコードでくくってやる必要があるようです。
 前にシフトインコード(0x0e)
 後ろにシフトアウトコード(0x0f)
ではさめばOKみたいです。

CCSID930のエンコード

CCSID930のバイト値を読み込んで変換し、Unicode 符号位置とUTF-8のバイト値を出力してみます。

Java文字コードの操作で参考にしたのは師匠のサイトで、素晴らしくまとまっています。
String、char、byteを使った文字コード関連のTips - CLOVER

まず、Javaエンコーディングでサポートされているか確認すると
「Cp930」としてサポートされていました。
https://docs.oracle.com/javase/jp/1.5.0/guide/intl/encoding.doc.html

変換

「あいうえおab」という文字を変換してみます。
処理のポイントとしては、
・1byteはそのまま変換
・2byteはシフトコードではさんで変換
をして対応しました。

バイト配列(byte[])がArrays.stream()でストリーム生成できないので、ちょっと悩みました。
IntStreamからストリームを生成してmap()して対応しました。

stream処理内でtry~catchするところが微妙です。

テストコードはこんな感じでやってみました。

EncodeCp930.java

byte[][] ebcdicHex = {
        {(byte)0x44, (byte)0x81}, // あ
        {(byte)0x44, (byte)0x82}, // い
        {(byte)0x44, (byte)0x83}, // う
        {(byte)0x44, (byte)0x84}, // え
        {(byte)0x44, (byte)0x85}, // お
        {(byte)0x62}, // a
        {(byte)0x63}, // b
};

Arrays.stream(ebcdicHex)
    .map(b -> {
        // 1byte
        if (b.length == 1)
                return b;
        // 2byte
        byte[] newBy = new byte[b.length + 2];
        System.arraycopy(b, 0, newBy, 1, b.length);
        newBy[0] = (byte)0x0e;
        newBy[b.length + 1] = (byte)0x0f;
        return newBy;
    }).forEach(
        b -> {
            try {
                String s = new String(b, "Cp930");
                byte[] bUTF8 = s.getBytes("UTF-8");
                System.out.println("【" + s + "】");
                System.out.printf("Unicode 符号位置 : %#x%n", (int)(s.toCharArray()[0]));
                System.out.print("UTF-8 バイト値 : ");
                IntStream.range(0, bUTF8.length)
                        .map(i -> bUTF8[i])
                        .forEach(bu -> { System.out.printf("%#x ", (byte)bu); });
                System.out.println();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
    );

実行

# java EncodeCp930
【あ】
Unicode 符号位置 : 0x3042
UTF-8 バイト値 : 0xe3 0x81 0x82 
【い】
Unicode 符号位置 : 0x3044
UTF-8 バイト値 : 0xe3 0x81 0x84 
【う】
Unicode 符号位置 : 0x3046
UTF-8 バイト値 : 0xe3 0x81 0x86 
【え】
Unicode 符号位置 : 0x3048
UTF-8 バイト値 : 0xe3 0x81 0x88 
【お】
Unicode 符号位置 : 0x304a
UTF-8 バイト値 : 0xe3 0x81 0x8a 
【a】
Unicode 符号位置 : 0x61
UTF-8 バイト値 : 0x61 
【b】
Unicode 符号位置 : 0x62
UTF-8 バイト値 : 0x62 

うまくいってるようです。

【参考】
CLOVER - String、char、byteを使った文字コード関連のTipsAdd Star
http://d.hatena.ne.jp/Kazuhira/20130224/1361700804
IBM漢字コードからUTF8やSJISに変換する表を手に入れたい→手に入れた
http://qiita.com/madilloar/items/12b9e270388c92d0482d
Javaメインフレーム文字コード変換するには
http://bitdatasci.blogspot.jp/2015/07/java.html