5

現在 Java 6 を使用しており (Java 7 に移行するオプションはありません)、java.util.regex パッケージを使用して、Unicode 文字を含む文字列のパターン マッチングを実行しようとしています。

java.lang.String が補助文字 (コードポイント > 0xFFFF の文字) をサポートしていることは知っていますが (Java 5 以降)、これらの文字でパターン マッチングを行う簡単な方法がわかりません。java.util.regex.Pattern では、4 桁を使用して 16 進数を表すことしかできません (例: \uFFFF)

ここで API が不足しているかどうかは誰にもわかりませんか?

4

2 に答える 2

7

補足文字を使用したパターンマッチングは行ったことがありませんが、2つの16ビット数値(UTF-16サロゲートペア)\ unnnn \ ummmmとして(パターンと文字列で)エンコードするのと同じくらい簡単だと思います。 これらの2つの数値(Java文字)をパターンと文字列の単一の文字として解釈するのに十分賢いjava.util.regex はずです(ただし、Javaはそれらを文字列の要素として2つの文字として認識します)。

2つのリンク:

JavaUnicodeエンコーディング

http://java.sun.com/developer/technicalArticles/Intl/Supplementary/

最後のリンクから(Java 5を参照):

java.util.regexパッケージが更新され、パターン文字列とターゲット文字列の両方に補足文字を含めることができるようになりました。補足文字は完全な単位として処理されます。

また、(ソースファイルの)エンコーディングとしてUTF8を使用している場合は、それらを直接書き込むこともできます(最後のリンクの「ソースファイルでの補足文字の表現」のセクションを参照)。

例えば:

    String pat1 = ".*\uD840\uDC00{2}.*";
    String s1  = "HI \uD840\uDC00\uD840\uDC00 BYE";
    System.out.println(s1.matches(pat1) + " len=" + s1.length());

    String pat2 = ".*\u0040\u0041{2}.*";
    String s2 = "HI \u0040\u0041\u0040\u0041 BYE";
    System.out.println(s2.matches(pat2) + " len=" + s2.length());

これは、Java 6でコンパイルされ、印刷されます

true len=11
false len=11

これは上記に同意します。最初のケースでは、サロゲートjava文字のペア(2つの16ビット文字、1つの上位Unicode文字)として表される単一のコードポイントがあり、{2}数量詞はペア(= codepoint)に適用されます。2番目の文字には2つの異なるBMP文字があり、数量詞は最後の文字に適用されます。したがって、一致しません。

ただし、文字列の長さは同じであることに注意してください(Javaは、Unicodeコードポイントではなく、Java文字をカウントして文字列の長さを測定するため)。

于 2011-03-23T18:41:21.720 に答える
2

最も簡単な解決策は、ソースコードにUTF-8エンコーディングを使用することです。次に、文字を直接入力します。プログラムで個別のコードユニットを指定する必要はありません。

ただし、Javaの不完全に公開されたUTF-16内部エンコーディングが文字クラスを台無しにするため、文字クラスにはまだ問題があります。JDK7までは完全なUnicodeを使用できません。その場合でも、間接\x{HHHHH}表記を使用して論理コードポイントを指定する必要があります。それでも、charclassにリテラルコードポイントを含めることはできませんが、を使用して回避することはできます\x{H..H}

不完全ですが、以前よりずっと良くなっています。UTF-16は常に妥協点です。内部でUTF-8またはUTF-32を使用するシステムには、これらの制限はありません。また、コードポイントと同一ではないコードユニットを指定することもありません。

于 2011-04-16T00:05:31.967 に答える