Interstage Application Server 使用上の注意 - Solaris (TM) Operating Environment -
目次 前ページ次ページ

第3章 注意事項> 3.16 JDK/JREの注意事項

3.16.8 Javaにおける文字化けの問題についての注意事項

 Javaにおける文字化けの問題についての注意事項を以下に述べます。
 Javaで異機種間結合を行う場合、あるいは、データベース接続を行う場合に起こる問題の1つに、文字化けの問題があります。例えば、Solaris OEマシンからWindowsマシンにネットワークを介して全角のチルダ記号('〜')を送ると、Windowsマシンで表示したときに文字化けが発生することがあります。
 これは既存の日本語コード(JIS、EUC、シフトJIS)をUnicodeに変換する際の変換規則が各ベンダによって異なるために起きる問題です。この問題はJava VMで解決できるものではなく、Javaのシステム開発者がこの問題を避けるための自衛的手段を講じる必要があります。
 この問題を理解するには、この問題が起きた背景を理解する必要があります。
 この背景を、以下で説明します。

■Unicodeの特徴

 UnicodeはUnicodeコンソーシアムが規定した文字コード体系です。世界の主要な言語のほとんどの文字を収録し、1つの文字コード体系で多国語処理を可能にしようという目的で策定されたものです。Unicodeは国際標準化機構(ISO)の規格であるISO/IEC 10646のベースになっています。
 Unicodeは主要な言語のほとんどの文字を収録しようとしたわけですが、この過程で次のような特徴が生まれました。

  1. 似たような文字が多数収録されている。

    Unicodeは、見た目が同じような文字であっても役割や用途が異なる文字は別文字として収録する、という方針で策定されています。例えば全角のチルダ記号('〜'、JIS X 0208では WAVE DASH(01-33))に似た文字は、以下のように6種類も収録されています。

    [表1] JIS X 0208 01-33(WAVE DASH、'〜')に似たUnicode文字

    コードポイント

    登録名

    U+301c

    WAVE DASH

    U+223c

    TILDE OPERATOR

    U+223d

    REVERSED TILDE

    U+223e

    INVERTED LAZY S

    U+223f

    SIGN WAVE

    U+ff5e

    FULLWIDTH TILDE


  2. 全角・半角を別文字として収録している。

    Unicodeでは、既存のコード系との互換性を保証するために、全角・半角を別文字として収録しています。例えば全角の'A'と半角の'A'はUnicodeでは異なる文字として収録されています。
    しかし、‘£’や‘¢’などのように日本語のコード系では全角の文字しかないものも、Unicodeでは全角・半角の2種類の文字が収録されています。

    [表2] JIS X 0208 01-82(POUND SIGN、'£')に対応可能なUnicode文字

    コードポイント

    登録名

    U+00a3

    POUND SIGN

    U+ffe1

    FULLWIDTH POUND SIGN

    [表3] JIS X 0208 01-81(CENT SIGN、'¢')に対応可能なUnicode文字

    コードポイント

    登録名

    U+00a2

    CENT SIGN

    U+ffe0

    FULLWIDTH CENT SIGN

■コード変換のベンダ依存性

 このようにUnicodeには似たような文字が多数収録されているので、既存の日本語コード系の文字をUnicodeのどの文字に対応させるべきか、いろいろな解釈が出てきます。ベンダ毎の解釈が異なるために、実際に各ベンダの変換規則に違いが出ています。代表的な例を以下に挙げます。

  1. UnicodeコンソーシアムではJIS漢字とUnicodeの変換規則を提供しています。また、JISでもJIS X 0221の付属書でJIS漢字とUnicodeの変換規則を定義しています。この2つで全角のダッシュ記号(JIS X 0201 01-29、'*')の変換規則が異なります。

    [表4] UnicodeコンソーシアムとJISの変換規則の違い

    JIS X 0208

    Unicodeへの変換

    01-29
    EM DASH ('*')

    Unicodeコンソーシアム:U+2015
    (HORIZONTAL BAR)

    JIS:U+2014
    (EM DASH)


  2. MicrosoftはWindowsでのシフトJIS <-> Unicodeの変換規則を独自に定義しています。Windowsの変換規則では日本語コードの全角文字はUnicodeの全角文字に対応させるというのが基本方針らしく、そのためJISの変換規則と異なる文字が幾つかあります。

    [表5] JISの変換規則とWindowsの変換規則の違いの例

    JIS X 0208

    Unicodeへの変換

    01-33
    WAVE DASH ('〜')

    JIS:U+301c
    (WAVE DASH)

    Windows:U+ff5e
    (FULLWIDTH TILDE)

    01-82
    POUND SIGN ('£')

    JIS:U+00a3
    (POUND SIGN)

    Windows:U+ffe1
    (FULLWIDTH POUND SIGN)

    01-81
    CENT SIGN ('¢')

    JIS:U+00a2
    (CENT SIGN)

    Windows:U+ffe0
    (FULLWIDTH CENT SIGN)

    これらの変換規則は、どれが正しくてどれが間違っているというものではありません。JISで定義されている変換規則はあくまでも参考であり、強制力を持つものではありません。どの文字をどの文字に対応させるかは、最終的には変換規則を作成する各ベンダに任せられているのが現状です。

■文字化けが起きる仕組み

 このように各ベンダにより変換規則が異なるために、Javaで異ベンダのシステムを連携させたときに、幾つかの文字が文字化けすることになります。
 例として、JavaでSolaris OEとWindowsをネットワーク接続し、テキストデータをやりとりするシステムを考えてみます。

[表6] 変換表の不整合による文字化けの例(ネットワーク通信時)

EUC

注1

Java(Unicode)

注2

シフトJIS

‘〜’

U+301c

未定義

未定義

U+ff5e

'〜'

注1: Solaris OE上でのJISの変換規則
注2: Windows上でのWindowsの変換規則

 Javaはプラットフォーム固有のコード系の文字データを読み込み、それをUnicodeに変換して処理します。データがネットワーク転送される際にはUnicode形式で送られ、それが他方のプラットフォーム固有のコード系に変換し直されます。
 この例ではSolaris OE上でのコード系にEUCを用いることにします。Solaris OE上のEUC <-> Unicode変換はJISの変換規則に従ったものです。Javaも基本的にはJISの変換規則に従ってEUC <-> Unicode変換を行います。
 Windowsの方ではコード系にシフトJISを用いることにします。WindowsにはWindowsのコード変換規則がありますので、JavaもWindowsの変換規則に従ってシフトJIS <-> Unicode変換を行います。
 ここで、Solaris OEからWindowsに全角のチルダ文字('〜')を送る場合を考えてみます。

  1. まず、JavaはSolaris OE上でEUCの'〜'を読み込み、Unicodeに変換します。Solaris OE上ではJISの変換規則に従った変換を行うので、'〜'はU+301cに変換されます。
  2. Unicodeに変換された'〜'(U+301c)がWindowsにネットワーク転送されます。
  3. 送られたUnicodeデータがWindows上でシフトJISに変換しなおされます。このときWindows上ではWindowsの変換規則に従った変換が行われます。
  4. しかし、Windowsの変換規則では'〜'に対応するUnicodeはU+ff5eです。Solaris OEから送られてきたUnicodeデータ(U+301c)は、Windowsの変換規則では対応する文字が定義されていません。このため、Windowsの変換規則でU+301cを変換するとシフトJISでは未定義文字になってしまいます。

 この逆も同じことで、Windows上の'〜'(U+ff5e)をSolaris OEに送った場合にも、JISの変換規則ではU+ff5eに対応する文字が定義されていないため、EUCに変換したときには未定義文字になってしまいます。
 Solaris OE上のコード変換もWindows上のコード変換も変換規則に問題はなく、Javaもそれに従って正しい変換を行っています。しかし、それぞれの変換規則が異なるために、2つの規則を組み合わせたときに正しい変換が行われなくなってしまいます。

■対処方法

 これらの問題は一方の変換規則をもう一方に合わせれば解決するように見えますが、そうすると今度は変換規則を変えた方で別の不整合が起こります。
 例えば始めの例で、Windows側の変換規則をJISの変換規則に変えてしまうと、Solaris OEから送られてきたUnicodeデータは正しく変換できるようになりますが、Windows上に保存されている既存のUnicodeデータが正しく変換できなくなります。
 最も単純かつ確実な対処方法は、文字化けが起きる文字をシステムで使わないようにすることです。文字化けが起きる文字はごく限られた少数のマルチバイト文字のみです。システム設計時にそれらの文字を使用しないよう注意する必要があります。
 あるいは、サーバがSolaris OEでクライアントがWindowsであるといったように使用するプラットフォームやデータベースが特定できる場合には、データ転送時にフィルタを掛けるという対処法もあります。
 例えばSolaris OEからWindowsに文字データを送信する際に、データ内に現れるU+301cを全てU+ff5eに変換してから転送すれば、Solaris OEからWindowsに正しく'〜'が送られるようになります。
 いずれにせよ、異なるベンダのシステムをつないだシステム開発を行う際には、システム開発者が事前に自衛的手段を講じて、文字化けの問題が起きるのを防ぐ必要があります。

<参考>
 以下は、Java2で前述の例(Solaris OEとWindowsでのネットワーク通信を行うシステム)を実現した場合に文字化けが起きる文字の一覧です。

JIS X 0208

Unicodeへの変換

01-33
WAVE DASH ('〜')

EUC:a1c1
SJIS:8160

Solaris OE上での変換:U+301c
(WAVE DASH)

Windows上での変換:U+ff5e
(FULLWIDTH TILDE)

01-34
DOUBLE VERTICAL LINE ('*')

EUC:a1c2
SJIS:8161

Solaris OE上での変換:U+2016
(DOUBLE VERTICAL LINE)

Windows上での変換:U+2225
(PARALLEL TO)

01-61
MINUS SIGN ('−')

EUC:a1dd
SJIS:817c

Solaris OE上での変換:U+2212
(MINUS SIGN)

Windows上での変換:U+ff0d
(FULLWIDTH HYPHEN-MINUS)

01-81
CENT SIGN ('¢')

EUC:a1f1
SJIS:8191

Solaris OE上での変換:U+00a2
(CENT SIGN)

Windows上での変換:U+ffe0
(FULLWIDTH CENT SIGN)

01-82
POUND SIGN ('£')

EUC:a1f2
SJIS:8192

Solaris OE上での変換:U+00a3
(POUND SIGN)

Windows上での変換:U+ffe1
(FULLWIDTH POUND SIGN)

02-44
NOT SIGN ('¬')

EUC:a2cc
SJIS:81ca

Solaris OE上での変換:U+00ac
(NOT SIGN)

Windows上での変換:U+ffe2
(FULLWIDTH NOT SIGN)


目次 前ページ次ページ

All Rights Reserved, Copyright(C) 富士通株式会社 2005