|
2004 年 5 月 English: Supplementary Characters in the Java Platform 要旨この記事では、Java プラットフォームで補助文字がどのようにサポートされるかを説明します。補助文字 (supplementary character) とは、Unicode 規格で定義される文字のうち、コードポイントが U+FFFF を超えているものを指します。これらの文字は、Java プログラミング言語の Java プラットフォームは、既存のアプリケーションに対する影響を最小限に抑えながら補助文字を処理できるよう機能拡張されています。新しい低レベル API を使うと、必要に応じて個々の文字を個別に操作することができます。一方、ほとんどのテキスト処理 API では、 この記事では、J2SE での拡張機能を詳しく説明するほか、アプリケーション開発者を対象として、完全な Unicode 文字セットを使用するために必要な変更を組み込むときのガイドラインを示します。 背景もともと Unicode は固定長 16 ビットの文字エンコーディングとして設計されました。この設計に基づいて、Java プログラミング言語の基本データ型 東アジアのマーケットでは、補助文字のサポートが一般的な業務要件になりつつあります。たとえば、政府関連の適用業務では中国の珍しい漢字を含む名前などを正しく表示するために補助文字をサポートする必要があります。出版業界では、歴史上の文字や異体字などを完全に表現するために補助文字が必要になります。中国政府は、中国新文字コード規格 GB18030 のサポートを求めています。GB18030 は、Unicode 文字セット全体をエンコードする文字エンコード方式であり、Unicode3.1 以降を仮定したときは補助文字を含みます。台湾の規格 CNS-11643 には、Unicode 3.1 に補助文字として登録された数多くの文字が含まれています。香港政府は広東語に必要な文字セットを定義しましたが、これらの文字の一部は Unicode の補助文字です。また、日本のいくつものベンダーが、50,000 文字以上の漢字の異体字を表すために補助文字空間内の大きなプライベート領域を使用し、独自のシステムから Java プラットフォームに基づくソリューションに移行することを計画しています。 したがって、今日の Java プラットフォームには、補助文字をサポートする機能だけではなく、アプリケーション内部で補助文字を容易にサポートできるようにする機能も必要です。補助文字によって Java プログラミング言語の基本的な前提条件が崩され、プログラミングモデルの根本的な変更が必要になる可能性があります。この問題に対する適正なソリューションを選択するために、Java Community Process(JCP)のもとに専門家グループが召集されました。このグループは、Java Specification Request for Unicode Supplementary Character Support の番号に基づき、JSR-204 専門家グループと呼ばれています。厳密には JSR-204 専門家グループの決定事項はJ2SE プラットフォームだけに適用されますが、Java 2 Platform, Enterprise Edition (J2EE) は J2SE プラットフォーム上に実装されるため、JSR-204 によるメリットは J2EE にも直接もたらされます。また、Java 2 Platform, Micro Edition (J2ME) の構成でも同じ設計アプローチが採用される予定です。 JSR-204 専門家グループが提案するソリューションを検証する前に、いくつかの基本概念や技術用語について理解しておく必要があります。 コードポイント、文字エンコーディング方式、UTF-16 などの用語の意味不都合なことに、補助文字の導入によって文字モデルが若干複雑になりました。従来の文字モデルは極めて単純であり、Java プラットフォームのような Unicode ベースの環境では、文字を 16 ビットで表現できました。しかし、現在はさらに複雑な表現技法(新しい文字モデル)が必要になっています。この記事では、新しい文字モデルの概要だけを簡単に説明します。詳しい説明については、Unicode Standard の第 2 章または Unicode 技術レポート 17「Character Encoding Model」 を参照してください。Unicode に精通している読者は、最後の定義の説明を除き、このセクションをスキップしてもかまいません。 文字 とは、テキストの概念的な最小単位で、固定の形状(グリフ によって表されます)や特定の値を持ちません。たとえば、"A" や ドイツ、フランス、その他のヨーロッパ諸国の通貨記号"€"などは文字です。 文字セット とは、複数の文字の集合です。たとえば、漢字は最初に中国で考案された文字セットで、これまで中国語、日本語、韓国語、ベトナム語で使われてきました。 コード化文字セット とは、個々の文字に一意の数値(コード)が割り当てられた文字セットです。たとえば、Unicode 規格の中核をなすコード化文字セットでは、文字 "A" に数値 004116 が、文字 "€" に数値 20AC16 が割り当てられています。Unicode 規格では常に 16 進数が使用され、数値の前に "U+" という接頭辞が付きます。たとえば、文字 "A" に対応する数値は "U+0041" と表記されます。 コードポイント とは、コード化文字セットで使用できる数値(コード)です。コード化文字セットでは 有効な コードポイントの範囲が定義されますが、すべてのコードポイントに文字が割り当てられるとは限りません。Unicode で使用できる有効なコードポイントの範囲は、U+0000 ~ U+10FFFF です。Unicode 4.0 では、これら 100 万個以上のコードポイントのうち、96,382 個のコードポイントに文字が割り当てられています。 補助文字 とは、U+10000 ~ U+10FFFF の範囲のコードポイントを持つ文字です。つまり、従来の 16 ビットの Unicode では表現できなかった文字です。これに対して、U+0000 ~ U+FFFF の範囲の文字は「基本多言語面 (Basic Multilingual Plane、BMP)」と呼ばれます。したがって、Unicode の各文字は、BMP または補助文字のどちらかに分類されます。 文字エンコーディング方式 とは、1 つ以上のコード化文字セットの数値(コード)から 1 つ以上の固定長 コード 単位のシーケンスへのマッピングです。最もよく使われるコード単位はバイトですが、16 ビットまたは 32 ビットの整数を内部処理に使用することもできます。UTF-32、UTF-16、UTF-8 は、Unicode 規格のコード化文字セット用の文字エンコーディング方式です。 UTF-32 では、単純に Unicode の個々のコードポイントを同じ値の 32 ビット整数として表します。UTF-32 は明らかに内部処理にとって最も簡便なエンコーディング方式ですが、汎用的な文字列表現として使用する場合には、必要以上にメモリが消費されます。 UTF-16 では、1 つまたは 2 つの符号なし 16 ビット コード単位のシーケンスを使って Unicode の個々のコードポイントをエンコードします。U+0000 ~ U+FFFF の範囲の文字 (BMP) は、同じ値を持つ 1 つの 16 ビットコード単位を使ってエンコードされます。補助文字は 2 つのコード単位を使ってエンコードされます。最初のコード単位は上位サロゲート領域 (U+D800 ~ U+DBFF) 、2 番目のコード単位は下位サロゲート領域 (U+DC00 ~ U+DFFF) 内の値になります。UTF-16 は概念的にはマルチバイト エンコーディング方式と似ていますが、重要な違いがあります。サロゲート領域 (U+D800 ~ U+DFFF) の値は UTF-16 の内部で使用するために予約されており、これらの値に文字が割り当てられることはありません (U+D800 ~ U+DFFF の値はコードポイントとして使用されません)。したがって、文字列内の個々のコード単位について、そのコード単位が 1 つのコード単位からなる文字を表しているのか、2 つのコード単位からなる文字の最初のコード単位または 2 番目のコード単位を表しているのかをソフトウェア側で判断することができます。これは従来のマルチバイト エンコーディング方式と比べて大きな改善といえます。従来の方式では、たとえば、0x41 というバイト値が文字 "A" を意味するのか、あるいは 2 バイト文字の 2 番目のバイトを表しているのかを判断できませんでした。 UTF-8 では、1 ~ 4 個のバイト(8 ビット)のシーケンスを使って、Unicode の個々のコードポイントをエンコードします。U+0000 ~ U+007F は 1 バイトでエンコードされます。U+0080 ~ U+07FF は 2 バイト、U+0800 ~ U+FFFF は 3 バイト、U+10000 ~ U+10FFFF は 4 バイトでそれぞれエンコードされます。UTF-8 では、0x00 ~ 0x7F のバイト値が常に U+0000 ~ U+007F のコードポイント (ASCII 文字セットに相当する基本ラテンブロック) を表します。これらのバイト値が他のコードポイントを表すことは決してありません。このような特性があるため、一定の ASCII 文字に特別な意味を割り当てるソフトウェアでも、UTF-8 を安心して使用できます。 次表に、各エンコーディング方式で数個の文字を表現した場合の比較を示します。
なお、この記事では、Java 2 プラットフォームで認識される文字シーケンスのすべてのコンテナをまとめて表現するために、「文字シーケンス」または「 さまざまな用語を紹介しましたが、次に、Java プラットフォームで補助文字をサポートするために、これらの技法がどのように適用されるかを説明します。 Java プラットフォーム上で補助文字をサポートするための設計アプローチJSR-204 専門家グループの一番の使命は、個々の文字および各形式の文字シーケンスにおいて、補助文字を Java API でどのように表現するかを決定することでした。この課題について、グループ内部で次に示すような複数のアプローチが提案され、試行錯誤が繰り返されました。
これらのアプローチの一部は早い時期に検討対象から除外されました。たとえば、基本データ型 その結果、複数のアプローチを階層的に組み合わせた次のような複合アプローチを決定しました。
このアプローチでは、個々の文字を必要に応じて概念的に簡潔かつ効率的に表現できると同時に、既存の API を変更して補助文字をサポートすることができます。また、個々の文字よりも文字シーケンスのほうが優先的に使用されるため、各国語に対応する必要のあるソフトウェアに適しています。 このアプローチでは 1 つの 次の 2 つのセクションでは、J2SE プラットフォーム上で補助文字をサポートするための実際の変更について説明します。最初のセクションは個々のコードポイントを操作する低レベル API に関する説明であり、2 番目のセクションは文字シーケンスを操作する高レベルインタフェースに関する説明です。 補助文字サポートのための変更 (1) : コードポイント用の API新たに追加された低レベル API は、(1) さまざまな 最も基本的な変換メソッドは、2 つの UTF-16 コード単位を 1 つのコードポイントに変換する 変換処理時に役立つ、コード単位とコードポイントを分析するためのメソッドもあります。Character クラスの なお、コードポイント用のほとんどのメソッドは、従来の
コードポイントを受け入れるほとんどのメソッドは、指定された 新しい API には、他の低レベル API を使って簡単に実装できる複数の便利なメソッドが含まれています。これらのメソッドは、使用頻度が非常に高いため J2SE プラットフォームに追加するのが適切であると JSR-204 専門家グループが判断したものです。一方、候補となった便利なメソッドのうち、JSR-204 専門家グループが API から除外したものもあります。ここでは、そのようなメソッドをユーザ自身が実装する方法を示します。たとえば、JSR-204 専門家グループは、検討の結果 /** この実装例を見ると、 /** また、たくさんの /** 一方、まったく別の解の方がふさわしい場合もあるかもしれません。通常、 System.out.println("Character " + String.valueOf(char) + " is invalid."); このような場合、新しい書式化 API を使う方がずっと簡潔な解決方法となります(この API は補助文字もサポートしています)。 System.out.printf("Character %c is invalid.%n", codePoint); この高レベル API を使用すると、コードが簡単になるだけではなく、別のいくつかのメリットを享受できます。メッセージの作成時に文字列を連結すると、メッセージのローカライズ(地域化)が極めて困難になります。上記の API を使用すると、文字列の連結を避けることができます。また、リソースバンドルに入れる文字列の数が 2 つから 1 つに減ります。 補助文字サポートのための変更 (2) : 文字シーケンスを取り扱うための機能拡張補助文字を使用可能にするための Java 2 プラットフォームへの変更の多くは、新しい API の追加ではなく既存の API への変更という形でなされています。文字シーケンスを取り扱うすべてのインタフェースの一般的な必要条件として、それぞれの機能に合った方法で補助文字を操作できるようにする必要があります。ここでは、このような要件を満たすための機能拡張について説明します。 Java プログラミング言語の識別子Java 言語仕様では、Unicode のすべての文字と数字が Java 識別子の中で使用できると規定されています。ほとんどの補助文字は文字または数字であるため、新しいコードポイント用メソッドを参照して識別子の中の有効な文字を定義するように、Java 言語仕様が変更されました。識別子を検出する必要のある javac コンパイラとその他のツールは、これらの新しいメソッドを使用するように変更されました。 ライブラリにおける補助文字のサポート既存のインタフェースを通じて補助文字をサポートするために、多くの J2SE ライブラリの機能が拡張されました。いくつかの例を次に示します。
文字の変換補助文字を表現できる文字エンコーディング方式の数は限られています。UTF-8 や UTF-16LE などの Unicode ベースのエンコーディング方式では、補助文字を正しく取り扱える変換機能が旧バージョンの J2RE の文字コンバータにすでに組み込まれていました。J2RE 5.0 では、補助文字を表現できる他のエンコーディング方式用のコンバータが更新されました。これらのコンバータは、GB18030、x-EUC-TW (CNS 11643 のすべての面を含む)、Big5-HKSCS (HKSCS-2001) 文字セットに対応しています。 ソースファイル内での補助文字の表現補助文字を直接表現できる文字エンコーディング方式を採用すれば、Java プログラミング言語のソースファイル内で補助文字をきわめて簡単に取り扱うことができます。たとえば、UTF-8 は最適なエンコーディング方式です。補助文字を直接表現できない文字エンコーディング方式を使用する場合に備えて、Java プログラミング言語には Unicode エスケープ構文が用意されています。この Unicode エスケープ構文には、補助文字を直接表現する機能は追加されていません。その代わり、文字を UTF-16 で表現した場合の 2 つのコード単位に対応する 2 つの連続した Unicode エスケープによって補助文字が表されます。たとえば、補助文字 U+20000 は "\uD840\uDC00" と表されます。通常、これらのエスケープシーケンスをユーザが直接書くのは困難です。そのため、必要な補助文字をサポートするエンコーディング方式で文字を書いた後、native2ascii などの変換ツールを使用して文字をエスケープシーケンスに変換することをお勧めします。 不都合なことに、プロパティファイルについては、アプリケーション内で新しい XML フォーマットを使用しない限り、エンコーディング方式が ISO 8859-1 に限定されます。したがって、補助文字を表すには常にエスケープシーケンスを使用する必要があります。この場合にも、必要な補助文字をサポートするエンコーディング方式で文字を書いた後、native2ascii などの変換ツールを使用して文字をエスケープシーケンスに変換してください。 Modified UTF-8Java プラットフォームにとって "Modified UTF-8" は新しいエンコーディング方式ではありません。アプリケーション開発者は、補助文字を含むテキストを標準 UTF-8 との間で変換するにあたって、Modified UTF-8 の特性を十分に把握しておく必要があります。特に注意を要する点は、一部の J2SE インタフェースにおいて、UTF-8 と類似しているものの、UTF-8 と互換性がないエンコーディング方式が使用されていることです。このエンコーディング方式は過去に、"Java modified UTF-8" または (誤って) 単に "UTF-8" と呼ばれていました。J2SE 5.0 では、ドキュメントが更新され、"Modified UTF-8" という呼称に統一されています。 Modified UTF-8 と標準 UTF-8 との非互換性は、2 つの相違点に起因しています。最初の相違点は、Modified UTF-8 では文字 U+0000 が 2 バイトのシーケンス 0xC0 0x80 で表現されるのに対して、標準 UTF-8 では 1 バイトの値 0x0 で表現されることです。2 番目の相違点として、Modified UTF-8 では、補助文字を UTF-16 で表現した場合の 2 つのサロゲートコード単位を別々にエンコードすることによって補助文字が表されます。個々の代用コード単位は 3 バイトで表されます。つまり、1 つの補助文字を表すために 6 バイトが使用されます。一方、標準 UTF-8 では、単一の 4 バイト シーケンスを使用して 1 つの補助文字を表します。 Modified UTF-8 が使われる箇所は、Java Virtual Machine (JVM) および JVM に関連するインタフェース (Java Native Interface、さまざまなツールインタフェース、Java クラスファイルなど)、 Modified UTF-8 と標準 UTF-8 は相互に互換性がないため、これら 2 種類のエンコーディング方式は厳密に使い分ける必要があります。Modified UTF-8 は上記の Java インタフェースだけで使用できます。それ以外の場合、特に Java プラットフォームと関連のないソフトウェアによって取り扱われる可能性のあるデータストリームでは、標準 UTF-8 を使用する必要があります。標準 UTF-8 を使用する必要がある場合、Modified UTF-8 との間で変換を実行する Java Native Interface ルーチンは使用できません。 ユーザアプリケーション内での補助文字のサポートここで、数多くの読者にとって最も興味のある問題「補助文字をサポートするために、どのような変更をアプリケーションに加えればよいのか」を説明します。 この問題に対する回答は、アプリケーション内部で実行するテキスト処理の内容と、使用する Java アプリケーション API のタイプに応じて異なります。 さまざまな形式の 個々の文字を独自に解釈するアプリケーション、個々の文字を Java プラットフォーム API に渡すアプリケーション、個々の文字を返すメソッドを呼び出すアプリケーションでは、それらの文字の値が有効かどうかをチェックする必要があります。ただし、ほとんどの場合、補助文字をサポートするための変更は不要です。たとえば、 個々の文字を独自に解釈するアプリケーション、個々の文字を Java プラットフォーム API に渡すアプリケーション、個々の文字を返すメソッドを呼び出すアプリケーションのうち、補助文字を取り扱う可能性のあるアプリケーションの場合に限り、補助文字をサポートするための変更をアプリケーションに加える必要があります。 すべてのテキストをコードポイント表現 (たとえば UTF-8 との間で変換を実行する必要があるアプリケーションについては、標準 UTF-8 または Modified UTF-8 のどちらを使用すべきのかを注意深く確認し、それぞれに適した Java プラットフォームユーティリティを使用しなければなりません。適正な UTF-8 の選択方法については、「Modified UTF-8」を参照してください。 補助文字を取り扱うユーザアプリケーションのテスト前のセクションの説明に従ってアプリケーションを変更する場合でも変更しない場合でも、補助文字の取り扱いに関してアプリケーションが正常に動作するかどうかをテストすることをお勧めします。グラフィカルユーザインタフェース (GUI) を使用しないアプリケーションについては、「ソースファイル内での補助文字の表現」の説明を参考にしてテストを実施してください。ここでは、GUI を使用するアプリケーションのテストに関する補足情報を示します。 テキストの入力に関しては、Java 2 SDK に コードポイント形式でのインプットメソッドが用意されています。このインプットメソッドでは、"\Uxxxxxx" という形式の文字列を入力できます。大文字 "U" は、エスケープシーケンスに 6 個の 16 進数が含まれる (補助文字がサポートされる) ことを示します。一方、小文字 "u" は、元来の形式のエスケープシーケンス "\uxxxx" を示します。この入力方式とそのドキュメントは、J2SDK の demo/jfc/CodePointIM ディレクトリにあります。 フォントを描画するには、必要な補助文字を描画できるフォントを用意する必要があります。このようなフォントの例として、James Kass の Code2001 フォントがあります。このフォントには、Deseret や Old Italic などのスクリプト用のグリフが含まれています。Java 2D ライブラリの新機能により、J2RE の lib/fonts/fallback ディレクトリにフォントをインストールすれば、そのフォントが 2D と XAWT の描画に使用される各論理フォントに自動的に追加されます。ユーザがフォント構成ファイルを編集する必要はありません。 上記の確認作業が完了すれば、アプリケーション内で補助文字を問題なく使用できると言ってよいでしょう。おめでとうございます! まとめ補助文字をサポートする機能が Java プラットフォームに組み込まれました。補助文字のサポートにおいては、ソースコードを変更しなくても、ほとんどのアプリケーションで補助文字を取り扱えるようにするアプローチが採用されています。個々の補助文字を操作/解釈するアプリケーションでは、 謝辞Java プラットフォームにおける補助文字のサポートは、Java Community Process(JCP)の内部組織である JSR-204 専門家グループによって設計開発されました。当専門家グループの仕様リードは、Sun Microsystems の奥津 正義と Brian Beck です。JSR-204 専門家グループのメンバーは、次のとおりです(敬称略、アルファベット順) : Craig Cummings(Oracle)、Mark Davis (IBM)、Markus Eble (SAP AG)、Jere Käpyaho (Nokia Corp.)、風間 一洋 (NTT)、数村 憲治 (富士通)、木村 英一(日本電気)、Changshin Lee (Tmax Soft Inc.)、村田 稔樹 (沖電気工業) リファレンスMasayoshi Okutsu, Brian Beck (ed.):Unicode Supplementary Character Support. Proposed Final Draft.Sun Microsystems, 2004. JavaTM 2 Platform Standard Edition 5.0 API Specification.Sun Microsystems, 2004. The Unicode Consortium:The Unicode Standard, Version 4.0.Addison-Wesley, 2003. Ken Whistler, Mark Davis:Character Encoding Model.Unicode Technical Report #17. The Unicode Consortium, 2000. James Kass:Code2001, a Plane 1 Unicode-based Font. 著者についてNorbert Lindenberg は、Sun Microsystems の Java Web Services グループにおけるJava 国際化のテクニカル・リードです。Sun に入社する前は、General Magic と Apple Computer において、さまざまな国際化プロジェクトに参画していました。彼は、ドイツのカールスルーヘ大学でコンピュータサイエンスの修士号を修めています。 奥津 正義は、Sun Microsystems の Java Web Services グループの国際化エンジニアで、現在 Java Specification Request 204, Unicode Supplementary Character Support の仕様リードを務めています。Sun に入社する前は、Digital Equipment Corporation において、さまざまな国際化プロジェクトに参画していました。彼は、日本の山形大学で電子工学の学士号を修めています。
1この Web サイトで使用している "Java Virtual Machine" または "JVM" という用語は、Java プラットフォーム用の仮想マシンを意味します。 | ||||||||||||||||||||||||||||||||||||||||||||||||
|
| ||||||||||||