ページの先頭行へ戻る
Symfoware Server V12.1.x アプリケーション開発ガイド(JDBCドライバ編)
FUJITSU Software

2.2.2 文字コード系に関する留意事項

Javaで異機種間結合を行う場合、あるいは、データベース接続を行う場合に起こる問題の1つに、文字化けの問題があります。たとえば、SolarisマシンからWindows(R)マシンにネットワークを介して全角のチルダ記号('~')を送ると、Windows(R)マシンで表示したときに文字化けしてしまうことがあります。

これは既存の日本語コード(JIS、EUC、シフトJIS)をUNICODEに変換する際の変換規則が各ベンダによって異なるために起きる問題です。この問題はJavaで解決できるものではなく、Javaのシステム開発者がこの問題を避けるための自衛的手段を講じる必要があります。

この問題を理解するには、この問題が起きた背景を理解する必要があります。

以下ではその背景を説明します。

UNICODEの特徴

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

UNICODEは主要な言語のほとんどの文字を収録しようとした訳ですが、この過程で次のような特徴が生まれました。

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

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

表2.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


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

UNICODEでは、既存の文字コード系との互換性を保証するために、全角と半角を別文字として収録しています。たとえば全角の'A'と半角の'A'はUNICODEでは異なる文字として収録されています。

しかし、'£'や'¢'などのように日本語の文字コード系では全角の文字しかないものも、UNICODEでは全角と半角の2種類の文字が収録されています。

表2.2 JIS X 0208 01-82(POUND SIGN、'£')に対応可能なUNICODE文字

コードポイント

登録名

U+00a3

POUND SIGN

U+ffe1

FULLWIDTH POUND SIGN


表2.3 JIS X 0208 01-81(CENT SIGN、'¢')に対応可能なUNICODE文字

コードポイント

登録名

U+00a2

CENT SIGN

U+ffe0

FULLWIDTH CENT SIGN


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

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

UNICODEコンソーシアムではJIS漢字とUNICODEの変換規則を提供

JISでもJIS X 0221の付属書でJIS漢字とUNICODEの変換規則を定義しています。この2つで全角のダッシュ記号(JIS X 0201 01-29、'*')の変換規則が異なります。

UNICODEコンソーシアムとJISの変換規則の違い


MicrosoftはWindows(R)でのシフトJISとUNICODEの相互変換規則を独自に定義

Windows(R)の変換規則では日本語コードの全角文字はUNICODEの全角文字に対応させるというのが基本方針で、そのためJISの変換規則と異なる文字がいくつかあります。

表2.4 JISの変換規則とWindows(R)の変換規則の違い

JIS X 0208

UNICODEへの変換

01-33
WAVE DASH ('~')

JIS:U+301c
(WAVE DASH)

Windows(R):U+ff5e
(FULLWIDTH TILDE)

01-82
POUND SIGN ('£')

JIS:U+00a3
(POUND SIGN)

Windows(R):U+ffe1
(FULLWIDTH POUND SIGN)

01-81
CENT SIGN ('¢')

JIS:U+00a2
(CENT SIGN)

Windows(R):U+ffe0
(FULLWIDTH CENT SIGN)


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

文字化けが起きる仕組み

このように各ベンダにより変換規則が異なるために、Javaで異ベンダのシステムを連携させたときに、いくつかの文字が文字化けすることになります。

例として、JavaでSolarisとWindows(R)をネットワーク接続し、テキストデータをやりとりするシステムを考えてみます。

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

EUCデータ
Solaris

  

Java(UNICODE)

  

シフトJISデータ
Windows(R)

'~'

U+301c

未定義

未定義

U+ff5e

'~'


Javaはプラットフォーム固有の文字コード系の文字データを読み込み、それをUNICODEに変換して処理します。データがネットワーク転送される際にはUNICODE形式で送られ、それが他方のプラットフォーム固有の文字コード系に変換し直されます。

この例ではSolaris上での文字コード系にEUCコードを用いることにします。Solaris上のEUCコードとUNICODEの相互変換はJISの変換規則に従ったものです。Javaも基本的にはJISの変換規則に従ってEUCコードとUNICODEの相互変換を行います。

Windows(R)の方では文字コード系にシフトJISを用いることにします。Windows(R)にはWindows(R)のコード変換規則があるので、JavaもWindows(R)の変換規則に従ってシフトJISとUNICODEの相互変換を行います。

ここで、SolarisからWindows(R)に全角のチルダ文字('~')を送る場合を考えてみます。

  1. JavaはSolaris上でEUCコードの'~'を読み込み、UNICODEに変換します。Solaris上ではJISの変換規則に従った変換を行うので、'~'はU+301cに変換されます。

  2. UNICODEに変換された'~'(U+301c)がWindows(R)にネットワーク転送されます。

  3. 送られたUNICODEデータがWindows(R)上でシフトJISに変換しなおされます。このときWindows(R)上ではWindows(R)の変換規則に従った変換が行われます。

  4. しかし、Windows(R)の変換規則では'~'に対応するUNICODEはU+ff5eです。Solarisから送られてきたUNICODEデータ(U+301c)は、Windows(R)の変換規則では対応する文字が定義されていません。このため、Windows(R)の変換規則でU+301cを変換するとシフトJISでは未定義文字になってしまいます。

この逆も同じことで、Windows(R)上の'~'(U+ff5e)をSolarisに送った場合にも、JISの変換規則ではU+ff5eに対応する文字が定義されていないため、EUCコードに変換したときには未定義文字になってしまいます。

Solaris上のコード変換もWindows(R)上のコード変換も変換規則に問題はなく、Javaもそれに従って正しい変換を行っています。しかしそれぞれの変換規則が異なるために、2つの規則を組み合わせたときに正しい変換が行われなくなってしまいます。

対処方法

これらの問題は一方の変換規則をもう一方に合わせれば解決するように見えますが、そうすると今度は変換規則を変えた方で別の不整合が起こります。

たとえば始めの例で、Windows(R)側の変換規則をJISの変換規則に変えてしまうと、Solarisから送られてきたUNICODEデータは正しく変換できるようになりますが、Windows(R)上に保存されている既存のUNICODEデータが正しく変換できなくなります。

最も単純かつ確実な対処方法は、文字化けが起きる文字をシステムで使わないようにすることです。文字化けが起きる文字はごく限られた少数のマルチバイト文字のみです。システム設計時にそれらの文字を使用しないよう注意する必要があります。

あるいは、サーバがSolarisでクライアントがWindows(R)であるといったように使用するプラットフォームやデータベースが特定できる場合には、データ転送時にフィルタを掛けるという対処法もあります。

たとえば、SolarisからWindows(R)に文字データを送信する際に、データ内に現れるU+301cをすべてU+ff5eに変換してから転送すれば、SolarisからWindows(R)に正しく'~'が送られるようになります。

いずれにせよ、異なるベンダのシステムをつないだシステム開発を行う際には、システム開発者が事前に自衛的手段を講じて、文字化けの問題が起きるのを防ぐ必要があります。

参考

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