LoginSignup
5
5

More than 5 years have passed since last update.

文字列中のサロゲートペアをU+FEFFに置き換えてみる

Posted at

はるか昔、Shift JIS で随分と苦しんだ気がするのに、Unicode (というか Java の char なので UTF-16BE かな?)を使っていてもサロゲートペアに苦しめられている気がする。
とりあえず、サロゲートペアを無かったことにしたい気分なので、U+FEFF(word breakしない幅ゼロの空白)に置き換えて見ようと思う。

正規表現でやってみる

サロゲートペアの範囲([\\uD800-\\uDFFF])を指定したら上手くマッチしてくれなかったので、コードポイントで U+10000 〜 U+10FFFF の範囲を指定しています。

http://d.hatena.ne.jp/miyakawa_taku/20160208/1454942816 で以下の記述をみつけたので、おそらくはマッチしないのが正しい振る舞いなのだろう。

UTF-16を使う場合、先行するサロゲートと後続するサロゲートのペアからなるシーケンスは、マッチにおいて単一のコードポイントとして扱わなければならない。

実際に正規表現で置き換えてみた。

String text = "[\uD83D\uDC27] ペンギン";
String replacement = "\uFEFF";

Pattern pattern = Pattern.compile(String.format("[\\x{%X}-\\x{%X}]",
                                                Character.MIN_SUPPLEMENTARY_CODE_POINT,
                                                Character.MAX_CODE_POINT));
String replaced = pattern.matcher(text).replaceAll(replacement);

System.out.println("    text = " + text);     //     text = [🐧] ペンギン
System.out.println("replaced = " + replaced); // replaced = [] ペンギン

Character.isSurrogate を使ってみる

単純に char[]for 文で回してみる。

ちなみに、これが一番早かった。toCharArray のなかが arraycopy なので、for 文で1つずつ char[i] に値をいれていくより早いのだろうと思う。

char[] replaced = text.toCharArray();
for (int i = 0; i < replaced.length; i++) {
    if (Character.isSurrogate(replaced[i])) {
        replaced[i] = '\uFEFF';
    }
}

System.out.println("    text = " + text);                 //     text = [🐧] ペンギン
System.out.println("replaced = " + new String(replaced)); // replaced = [] ペンギン

別解。個人的にはこっちのほうが好みな書き方。

char[] replaced = new char[text.length()];
for (int i = 0; i < replaced.length; i++) {
    char ch = text.charAt(i);
    replaced[i] = Character.isSurrogate(ch) ? '\uFEFF' : ch;
}
System.out.println("    text = " + text);
System.out.println("replaced = " + new String(replaced));
5
5
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
5
5