Javaの文字セットコード入門(六)Javaの補足文字
2869 ワード
JavaはUnicodeに天然のサポートを提供していると言われていますが、この話はずっと前から偽物でした(しかし、かつては本当でした)、実際にはJDK 5.0までJavaはUnicodeの足どりに追いついたばかりで、増補文字のサポートを提供し始めました.
現在のUnicodeコード空間はU+0000からU+10 FFFFで、全部で1114112個のコードビットがあり、そのうち1112064個のコードビットしか合法的ではありません(算術をしてあげますが、2048個のコードビットが合法的ではありません).しかし、現在のUnicodeにはこんなに多くの文字があるわけではありませんが、実際には多くのコードビットが空いていて、Unicode 4.0規範まで、96382個の符号ビットだけが文字を割り当てられている(いずれにしても、多くの人が考えている65536文字よりずっと多い).このうちU+0000~U+FFFFの部分を基本多言語面(Basic Multilingual Plane,BMP)と呼ぶ.U+10000以上の文字を補足文字と呼ぶ.Javaでは(Java 1.5以降)、補足文字は2つのchar型変数で表され、この2つのchar型変数はいわゆるsurrogate pair(最下位では実際にはintで表される)を構成する.1番目のchar型変数の範囲を「高エージェント部分」(high-surrogates range、「uD 800から」uDFF、1024符号ビット)と呼び、2番目のchar型変数の範囲をlow-surrogates range(「uDC 00から」uDFF、1024符号ビット)と呼び、surrogate pairを用いて表す文字数は1024の平方計1048576個であり、BMPの65536符号ビットを加えると、2048個の不正な符号ビットを除いて、ちょうど1112064個の符号ビットです.
Unicodeのコード空間については、実際には少し油断すると間違いを犯すところがあります.例えば,U+0000からU+FFFFまでの部分を基本多言語面(Basic Multilingual Plane,BMP)と呼ぶことが知られており,この範囲内の文字はUTF-16符号化を用いる場合,char型変数1つで保存できる.この範囲をよく見ると、65536ほどあるはずなので、単バイトのUTF-16符号化で65536文字を表すことができ、Unicodeの基本的な多言語面には65536文字が含まれているとも言えますが、さっき言ったsurrogate pair、1つのUTF-16が表す補完文字(もう一度、2つのchar型変数が必要な文字)を考えてみてください.2つの普通の文字ではなく、補完文字として正しく認識するにはどうすればいいのでしょうか.答えは、最初のcharが高エージェント範囲内にあるかどうかを見て、2番目のcharが低エージェント範囲内にあるかどうかを決定することです.これは、高エージェントと低エージェントが占める2048ビット(0 xD 800から0 xDFF)が他の文字に割り当てられないことを意味します.
しかし、これはUTF-16のような符号化方法であり、Unicodeのような文字セットには?Unicodeの番号の中で、U+D 800からU+DFFまで文字の割り当てがありますか?答えはない!これは典型的な文字セットが符号化方法を容易にするための手配である(彼らにそう聞く目的は?もちろん基本的な多言語面の文字と1つのchar型のUTF-16符号化の文字が1つ1つ対応できることを望んで、少し面倒で、そこからUTF-16とUnicodeの間の深い淵源と結合も見ることができる).つまり、UnicodeでもUTF-16でもエンコードされた文字は、0 x 0000~0 xFFFFの範囲で63488文字しかありません.これは、最初のCPUが無理にマルチメディアアプリケーションとして使われていたように、CPUはハードウェアからマルチメディアアプリケーションをサポートしていることを修正せざるを得なくなった.
望ましくないが、ここではコードポイントとコードユニットに関する概念を話さなければならない.
コードポイント(Code Point)とは、Unicodeに文字が割り当てられた番号を指し、1文字が1つのコードポイントしか占めていない.例えば、文字「漢」といえば、U+6 C 49である.コードユニット(Code Unit)とは、符号化方法において、1文字を符号化した後に占める最小の記憶ユニットを指す.例えばUTF-8では、1文字を1、2、または3の4バイトに符号化することができるため、コードユニットは1バイトである.UTF-16では、1文字が1つまたは2つのcharに符号化できるため、コードユニットは2バイト(charである)になります(charよりも小さいUTF-16符号化された文字が見つからないので、へへへ).もっとくどくど言うと、1文字で、1つのコード点にしか対応していませんが、複数のコードユニット(すなわち、2つのcharに符号化される可能性があります)がある可能性があります.
以上の概念は決して学術的な早口令ではありません.これは、自分がどの文字を使用するかを統一的に指定したい場合、コードポイント(つまり、Unicodeのいくつかの文字を使用するプログラム)を使用することがコードユニットを使用するよりも常に良いことを意味します.(そうすると状況を区別しなければならないので、16進数を提供したり、2つを提供したりすることもあります).
例えば、補完文字がありますか?(ははは、3つの疑問符を見ましたよね?私のシステムではこの文字は表示されません)Unicodeの番号はU+2 F 81 Aで、プログラムでこの文字を使用する必要がある場合は、このように書くことができます.
後のforループはこの文字のUTF-16符号化をプリントアウトしましたが、d 87 edc 1 aで気づきましたか?この文字は2つのchar型変数になり、そのうち0 xd 87 eは高エージェント部分の値、0 xdc 1 aは低エージェントの値です.
現在のUnicodeコード空間はU+0000からU+10 FFFFで、全部で1114112個のコードビットがあり、そのうち1112064個のコードビットしか合法的ではありません(算術をしてあげますが、2048個のコードビットが合法的ではありません).しかし、現在のUnicodeにはこんなに多くの文字があるわけではありませんが、実際には多くのコードビットが空いていて、Unicode 4.0規範まで、96382個の符号ビットだけが文字を割り当てられている(いずれにしても、多くの人が考えている65536文字よりずっと多い).このうちU+0000~U+FFFFの部分を基本多言語面(Basic Multilingual Plane,BMP)と呼ぶ.U+10000以上の文字を補足文字と呼ぶ.Javaでは(Java 1.5以降)、補足文字は2つのchar型変数で表され、この2つのchar型変数はいわゆるsurrogate pair(最下位では実際にはintで表される)を構成する.1番目のchar型変数の範囲を「高エージェント部分」(high-surrogates range、「uD 800から」uDFF、1024符号ビット)と呼び、2番目のchar型変数の範囲をlow-surrogates range(「uDC 00から」uDFF、1024符号ビット)と呼び、surrogate pairを用いて表す文字数は1024の平方計1048576個であり、BMPの65536符号ビットを加えると、2048個の不正な符号ビットを除いて、ちょうど1112064個の符号ビットです.
Unicodeのコード空間については、実際には少し油断すると間違いを犯すところがあります.例えば,U+0000からU+FFFFまでの部分を基本多言語面(Basic Multilingual Plane,BMP)と呼ぶことが知られており,この範囲内の文字はUTF-16符号化を用いる場合,char型変数1つで保存できる.この範囲をよく見ると、65536ほどあるはずなので、単バイトのUTF-16符号化で65536文字を表すことができ、Unicodeの基本的な多言語面には65536文字が含まれているとも言えますが、さっき言ったsurrogate pair、1つのUTF-16が表す補完文字(もう一度、2つのchar型変数が必要な文字)を考えてみてください.2つの普通の文字ではなく、補完文字として正しく認識するにはどうすればいいのでしょうか.答えは、最初のcharが高エージェント範囲内にあるかどうかを見て、2番目のcharが低エージェント範囲内にあるかどうかを決定することです.これは、高エージェントと低エージェントが占める2048ビット(0 xD 800から0 xDFF)が他の文字に割り当てられないことを意味します.
しかし、これはUTF-16のような符号化方法であり、Unicodeのような文字セットには?Unicodeの番号の中で、U+D 800からU+DFFまで文字の割り当てがありますか?答えはない!これは典型的な文字セットが符号化方法を容易にするための手配である(彼らにそう聞く目的は?もちろん基本的な多言語面の文字と1つのchar型のUTF-16符号化の文字が1つ1つ対応できることを望んで、少し面倒で、そこからUTF-16とUnicodeの間の深い淵源と結合も見ることができる).つまり、UnicodeでもUTF-16でもエンコードされた文字は、0 x 0000~0 xFFFFの範囲で63488文字しかありません.これは、最初のCPUが無理にマルチメディアアプリケーションとして使われていたように、CPUはハードウェアからマルチメディアアプリケーションをサポートしていることを修正せざるを得なくなった.
望ましくないが、ここではコードポイントとコードユニットに関する概念を話さなければならない.
コードポイント(Code Point)とは、Unicodeに文字が割り当てられた番号を指し、1文字が1つのコードポイントしか占めていない.例えば、文字「漢」といえば、U+6 C 49である.コードユニット(Code Unit)とは、符号化方法において、1文字を符号化した後に占める最小の記憶ユニットを指す.例えばUTF-8では、1文字を1、2、または3の4バイトに符号化することができるため、コードユニットは1バイトである.UTF-16では、1文字が1つまたは2つのcharに符号化できるため、コードユニットは2バイト(charである)になります(charよりも小さいUTF-16符号化された文字が見つからないので、へへへ).もっとくどくど言うと、1文字で、1つのコード点にしか対応していませんが、複数のコードユニット(すなわち、2つのcharに符号化される可能性があります)がある可能性があります.
以上の概念は決して学術的な早口令ではありません.これは、自分がどの文字を使用するかを統一的に指定したい場合、コードポイント(つまり、Unicodeのいくつかの文字を使用するプログラム)を使用することがコードユニットを使用するよりも常に良いことを意味します.(そうすると状況を区別しなければならないので、16進数を提供したり、2つを提供したりすることもあります).
例えば、補完文字がありますか?(ははは、3つの疑問符を見ましたよね?私のシステムではこの文字は表示されません)Unicodeの番号はU+2 F 81 Aで、プログラムでこの文字を使用する必要がある場合は、このように書くことができます.
String s=String.valueOf(Character.toChars(0x2F81A));
char[]chars=s.toCharArray();
for(char c:chars){
System.out.format("%x",(short)c);
}
後のforループはこの文字のUTF-16符号化をプリントアウトしましたが、d 87 edc 1 aで気づきましたか?この文字は2つのchar型変数になり、そのうち0 xd 87 eは高エージェント部分の値、0 xdc 1 aは低エージェントの値です.