Поддержка Java для не-BMP символов Unicode (т.е. кодовых точек> 0xFFFF) в их библиотеке регулярных выражений? - PullRequest
5 голосов
/ 23 марта 2011

В настоящее время я использую Java 6 (у меня нет возможности перейти на Java 7), и я пытаюсь использовать пакет java.util.regex для сопоставления с образцом строк, содержащих символы Unicode.

Я знаю, что java.lang.String поддерживает дополнительные символы (то есть символы с кодовыми точками> 0xFFFF) (начиная с Java 5), ​​но я не вижу простого способа сопоставления с этими символами. java.util.regex.Pattern по-прежнему разрешает представлять шестнадцатеричные числа только с помощью 4 цифр (например, \ uFFFF)

Кто-нибудь знает, если я пропускаю API здесь?

Ответы [ 2 ]

6 голосов
/ 23 марта 2011

Я никогда не сопоставлял шаблоны с дополнительными символами, но я думаю, что это так же просто, как кодировать их (в шаблонах и строках), как два 16-битных числа (суррогатная пара UTF-16) \ unnnn \ ummmm. java.util.regex должно быть достаточно умно, чтобы интерпретировать эти два числа (символы Java) как один символ в шаблонах и строках (хотя Java все равно будет рассматривать их как два символа как элементы строки).

Две ссылки:

кодировка Java Unicode

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-символов (два 16-битных символа, один дополнительный символ Unicode), и квантификатор {2} применяется к паре (= кодовая точка). Во втором у нас есть два разных символа BMP, квантификатор применяется к последнему - следовательно, нет соответствия.

Обратите внимание, однако, что длина строки одинакова (поскольку Java измеряет длину строки, считая символы Java, а не кодовые точки Unicode).

2 голосов
/ 16 апреля 2011

Самое простое решение - использовать кодировку UTF-8 для вашего исходного кода.Затем просто вставьте символы непосредственно.Вы никогда не должны когда-либо указывать отдельные блоки кода в любой программе.

Тем не менее, существует проблема с классами символов, потому что внутренняя кодировка UTF-16 в Java испортила их.Вы не можете использовать полный Unicode до JDK7, где даже тогда вам придется указывать логические кодовые точки, используя косвенную запись \x{HHHHH}.Вы по-прежнему не сможете получить буквальный код в charclass, но вы можете увернуться от него с помощью \x{H..H}.

Несовершенно, но это намного лучше, чем было.UTF-16 - это всегда компромисс.Системы, которые используют UTF-8 или UTF-32 внутри, не имеют этих ограничений.Они также никогда не заставляют вас указывать кодовые единицы, которые не идентичны кодовым точкам.

...