2015年9月8日火曜日

Javaでメインフレームの文字コード変換するには(その2)

こんにちは、寺田です。



前回の私の投稿『Javaでメインフレームの文字コード変換するには』では、JavaでIBMメインフレームの文字コードを変換する方法について紹介しました。今回は、富士通や日立のメインフレームの文字コード変換もJavaでできるのか?というお話をしたいと思います。

このブログでも度々出てきますが、富士通メインフレームで使用している文字コードは、JEFと呼ばれています。また、日立メインフレームの文字コードは、KEISと呼ばれています。

前回、IBMメインフレームの文字コードをJavaでコード変換する場合、Cp930またはCp939というエンコーディングを使用すれば、簡単に文字コード変換ができるという話をしました。
では、JEFやKEISはどうかというと、残念ながら、JavaにJEFやKEISに該当するエンコーディングは存在しません。

そこで、どうすればJavaでコード変換ができるか考えてみました。

まず1つ目の方法として、計算によるコード変換が考えられます。
JEFの文字コードとJISコードは、計算によって相互に変換することができます。さらに、Javaには、JISコードのエンコーディングがあるので、
  JEF ←(計算)→ JIS ←(エンコーディング) → Unicode
とすれば、JEFとUnicodeのコード変換が可能です。

ただし、先日の綱島さんの投稿『富士通メインフレームの文字コード(最終回)』に書かれているとおり、計算によるコード変換には「落とし穴」があるので注意が必要です。

2つ目の方法として、エンコーディングEUC-JPを使用する方法です。
JEFは、拡張漢字と一部例外を除けば、EUC-JPと同じです。EUC-JPは、昔のUNIXでよく使われていた文字コードですね。
一部例外とは、JEFでは全角スペースは 0x4040 ですが、EUC-JPでは 0xA1A1 となります。
また、機種依存文字が正しく変換できません。これらの例外文字については、独自に変換テーブルでも作って変換する必要があります。

なお、日立のKEISも、JEFと同様にEUC-JP相当の文字コードなので、上記2つの方法でコード変換が可能です。

以下に、極々簡単な変換ロジックを書いてみました。
全角スペースのときは、直接 0x4040 に変換しています。本当は、機種依存文字やEUC-JPにない文字が含まれている場合など、もっともっとちゃんと考える必要がありますよ。

(Unicode → JEF)

 try {
     String unicode = "JEF 漢字コード";
     byte[] jef = new byte[unicode.length() * 2];
     for (int i = 0; i < unicode.length(); i++) {
         char ch = unicode.charAt(i);
         if (ch == 0x3000) {    // 全角スペースのとき
             jef[i * 2] = (byte)0x40;
             jef[i * 2 + 1] = (byte)0x40;
         } else {
             byte[] buf = String.valueOf(ch).getBytes("EUC-JP");
             System.arraycopy(buf, 0, jef, i * 2, buf.length);
         }
     }
 } catch(UnsupportedEncodingException e) {
 }


(JEF → Unicode)

 try {
     // "JEF 漢字コード"のバイト配列
     byte[] jef = {(byte)0xa3, (byte)0xca, (byte)0xa3, (byte)0xc5, (byte)0xa3,
                    (byte)0xc6, (byte)0x40, (byte)0x40, (byte)0xb4, (byte)0xc1,
                    (byte)0xbb, (byte)0xfa, (byte)0xa5, (byte)0xb3, (byte)0xa1,
                    (byte)0xbc, (byte)0xa5, (byte)0xc9};
     String unicode = "";
     for (int i = 0; i < jef.length; i += 2) {
         byte[] buf = new byte[2];
         System.arraycopy(jef, i, buf, 0, 2);
         String uni = "";
         if (buf[0] == (byte)0x40 && buf[1] == (byte)0x40) {
             uni = " ";
         } else {
             uni = new String(buf, "EUC-JP");
         }
         unicode += uni;
     }
 } catch(UnsupportedEncodingException e) {
 }


さて、ここまでは、全角(2バイト)文字の変換についての話です。

IBMの文字コードの場合は、全角・半角が混ざった文字列でも、Cp930/Cp939のエンコーディングを使うと一発で変換できたので良かったのですが、富士通・日立の文字コードでそれをやろうと思うと・・・。

ちょっと難しくなるので、いずれお話したいと思います。
いつか、JavaのJEF・KEISコード変換クラスでも作成して公開できればなぁ・・・と思っています。

0 件のコメント:

コメントを投稿