LoginSignup
15
12

More than 5 years have passed since last update.

JavaでUnicodeのサロゲートペアを扱う練習

Posted at

文字コードの復習をちょっとしてたら、Unicodeのサロゲートペアって今まで気にしたこと無かったことに気が付きました。
ということで、お仕事でも扱うJavaで、サロゲートペアの文字列を組み立てたり、文字数をカウントしたりする練習をしました。

Java 1.4まではサロゲートペアは考慮されてませんでしたが、1.5になり、サロゲートペアを考慮したAPIが追加されました。そこで、上記テストコードでは1.4系までのAPIと、1.5で追加されたAPIを呼び出してみて、挙動を比べてます。

まず char 型でサロゲートペアを表現してみます。上位サロゲート、下位サロゲートをそれぞれ別のchar型変数として分け、配列に組み込んでます。

char c1 = '\u3042'; // HIRAGANA LETTER A, cp=12354
char c2 = '\uD842'; // tuchi-yoshi (high), cp=134071
char c3 = '\uDFB7'; // tuchi-yoshi (low), cp=134071
char c4 = '\u30D5'; // katakana fu, cp=12501
char c5 = '\u309A'; // handakuten, cp=12442
char c6 = '\uD842'; // kuchi + shichi (high), cp=134047
char c7 = '\uDF9F'; // kuchi + shichi (low), cp=134047
String s = new String(new char[] { c1, c2, c3, c4, c5, c6, c7 });
assertEquals(s, "\u3042\uD842\uDFB7\u30D5\u309A\uD842\uDF9F");

続いてサロゲートペアを考慮しない String.length()String.charAt() を使って文字列をコピーしてみます。最後の assertEquals() を見ると、サロゲートペアが分割された状態の int[] から生成した文字列と一致しています。上位サロゲート・下位サロゲートをそれぞれ独立した一文字として扱い、コピーしている様子が確認できます。

int len = s.length();
assertEquals(len, 7); // ignores surrogate pair :P
int[] actualCps = new int[len];
for (int i = 0; i < len; i++) {
    char c = s.charAt(i);
    actualCps[i] = (int) c;
}
// Ignores surrogate pairs... :(
// BUT JavaScript unicode escape in browser accepts this format...:(
assertEquals(actualCps, new int[] { 0x3042, 0xD842, 0xDFB7, 0x30D5, 0x309A, 0xD842, 0xDF9F });

今度はサロゲートペアを考慮する String.codePointCount()String.codePointAt() を使ってみます。最後の assertEquals() を見ると、サロゲートペア対象文字をUnicodeコードポイントの16進数で表現した文字列と同じになります。サロゲートペアを1文字としてカウントし、扱えている様子が確認できます。

int countOfCp = s.codePointCount(0, len);
assertEquals(countOfCp, 5); // GOOD.

actualCps = new int[countOfCp];
for (int i = 0, j = 0, cp; i < len; i += Character.charCount(cp)) {
    cp = s.codePointAt(i);
    actualCps[j++] = cp;
}
// GOOD.
assertEquals(actualCps, new int[] { 0x3042, 0x20BB7, 0x30D5, 0x309A, 0x20B9F });

参考:

15
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
12