Как программно определить в Java, какая версия Unicode поддерживается? - PullRequest
7 голосов
/ 04 августа 2011

В связи с тем, что код Java может выполняться на любой виртуальной машине Java, я хотел бы знать, как можно программно определить, какая версия Unicode поддерживается?

Ответы [ 6 ]

7 голосов
/ 04 августа 2011

Самый простой, но наихудший способ сделать это - выбрать код, новый для каждого выпуска Unicode, и проверить его свойства символов. Или вы можете проверить его общую категорию с помощью регулярного выражения. Вот некоторые выбранные кодовые точки:

  • Юникод 6.0.0:

    Ꞡ  U+A7A0 GC=Lu SC=Latin    LATIN CAPITAL LETTER G WITH OBLIQUE STROKE
    ₹  U+20B9 GC=Sc SC=Common   INDIAN RUPEE SIGN
    ₜ  U+209C GC=Lm SC=Latin    LATIN SUBSCRIPT SMALL LETTER T
    
  • Юникод 5.2:

    Ɒ  U+2C70 GC=Lu SC=Latin    LATIN CAPITAL LETTER TURNED ALPHA
    ‭⅐ U+2150 GC=No SC=Common   VULGAR FRACTION ONE SEVENTH
    ⸱  U+2E31 GC=Po SC=Common   WORD SEPARATOR MIDDLE DOT
    
  • Юникод 5.1:

    ‭ꝺ  U+A77A GC=Ll SC=Latin    LATIN SMALL LETTER INSULAR D
    Ᵹ  U+A77D GC=Lu SC=Latin    LATIN CAPITAL LETTER INSULAR 
    ⚼  U+26BC GC=So SC=Common    SESQUIQUADRATE
    
  • Юникод 5.0:

    Ⱶ  U+2C75 GC=Lu SC=Latin    LATIN CAPITAL LETTER HALF H
    ɂ  U+0242 GC=Ll SC=Latin    LATIN SMALL LETTER GLOTTAL STOP
    ⬔  U+2B14 GC=So SC=Common  SQUARE WITH UPPER RIGHT DIAGONAL HALF BLACK
    

Я включил общую категорию и свойство сценария, хотя вы можете проверить сценарий только в JDK7, первом выпуске Java, который это поддерживает.

Я нашел эти кодовые точки, выполнив такие команды из командной строки:

% unichars -gs '\p{Age=5.1}'
% unichars -gs '\p{Lu}' '\p{Age=5.0}'

Где это программа unichars . Он найдет свойства, поддерживаемые в базе данных символов Unicode только для той версии UCD, которую поддерживает версия Perl, которую вы используете.

Мне также нравится сортировка выходных данных, поэтому я обычно запускаю

 % unichars -gs '\p{Alphabetic}' '\p{Age=6.0}' | ucsort | less -r

где это программа ucsort , которая сортирует текст в соответствии с алгоритмом сортировки Unicode.

Однако в Perl, в отличие от Java, это легко узнать. Например, если вы запустите это из командной строки (да, есть и API для программиста), вы найдете:

$ corelist -a Unicode
    v5.6.2     3.0.1     
    v5.8.0     3.2.0     
    v5.8.1     4.0.0 
    v5.8.8     4.1.0
    v5.10.0    5.0.0     
    v5.10.1    5.1.0 
    v5.12.0    5.2.0 
    v5.14.0    6.0.0

Это показывает, что Perl версии 5.14.0 был первым, кто поддержал Unicode 6.0.0. Я полагаю, что для Java нет API, который бы предоставлял вам эту информацию напрямую, поэтому вам придется жестко кодировать таблицы, отображающие версии Java и версии Unicode, или использовать эмпирический метод тестирования кодовых точек для свойств. Под эмпирическим путем я подразумеваю эквивалент такого рода вещей:

% ruby -le 'print "\u2C75" =~ /\p{Lu}/ ? "pass 5.2" : "fail 5.2"'
pass 5.2
% ruby -le 'print "\uA7A0" =~ /\p{Lu}/ ? "pass 6.0" : "fail 6.0"'
fail 6.0
% ruby -v
ruby 1.9.2p0 (2010-08-18 revision 29036) [i386-darwin9.8.0]

% perl -le 'print "\x{2C75}" =~ /\p{Lu}/ ? "pass 5.2" : "fail 5.2"'
pass 5.2
% perl -le 'print "\x{A7A0}" =~ /\p{Lu}/ ? "pass 6.0" : "fail 6.0"'
pass 6.0
% perl -v
This is perl 5, version 14, subversion 0 (v5.14.0) built for darwin-2level

Чтобы узнать возраст конкретной кодовой точки, запустите на ней uniprops -a следующим образом:

% uniprops -a 10424
U+10424 ‹?› \N{DESERET CAPITAL LETTER EN}
 \w \pL \p{LC} \p{L_} \p{L&} \p{Lu}
 All Any Alnum Alpha Alphabetic Assigned InDeseret Cased Cased_Letter LC Changes_When_Casefolded CWCF Changes_When_Casemapped CWCM Changes_When_Lowercased CWL Changes_When_NFKC_Casefolded CWKCF Deseret Dsrt Lu L Gr_Base Grapheme_Base Graph GrBase ID_Continue IDC ID_Start IDS Letter L_ Uppercase_Letter Print Upper Uppercase Word XID_Continue XIDC XID_Start XIDS X_POSIX_Alnum X_POSIX_Alpha X_POSIX_Graph X_POSIX_Print X_POSIX_Upper X_POSIX_Word
 Age=3.1 Bidi_Class=L Bidi_Class=Left_To_Right BC=L Block=Deseret Canonical_Combining_Class=0 Canonical_Combining_Class=Not_Reordered CCC=NR Canonical_Combining_Class=NR Decomposition_Type=None DT=None Script=Deseret East_Asian_Width=Neutral Grapheme_Cluster_Break=Other GCB=XX Grapheme_Cluster_Break=XX Hangul_Syllable_Type=NA Hangul_Syllable_Type=Not_Applicable HST=NA Joining_Group=No_Joining_Group JG=NoJoiningGroup Joining_Type=Non_Joining JT=U Joining_Type=U Line_Break=AL Line_Break=Alphabetic LB=AL Numeric_Type=None NT=None Numeric_Value=NaN NV=NaN Present_In=3.1 IN=3.1 Present_In=3.2 IN=3.2 Present_In=4.0 IN=4.0 Present_In=4.1 IN=4.1 Present_In=5.0 IN=5.0 Present_In=5.1 IN=5.1 Present_In=5.2 IN=5.2 Present_In=6.0 IN=6.0 SC=Dsrt Script=Dsrt Sentence_Break=UP Sentence_Break=Upper SB=UP Word_Break=ALetter WB=LE Word_Break=LE _X_Begin

Все мои инструменты Unicode доступны в комплекте Unicode :: Tussle , включая unichars , uninames , uniquote , ucsort и многие другие.

Улучшения Java 1.7

JDK7 значительно облегчает работу с Unicode. Я немного об этом говорю в конце своего выступления по выбору поддержки OSCON Unicode. Я думал о том, чтобы составить таблицу того, какие языки поддерживают какие версии Unicode, в каких версиях этих языков, но в итоге я отказался от этого, чтобы сказать людям просто получить последнюю версию каждого языка. Например, я знаю, что Unicode 6.0.0 поддерживается Java 1.7, Perl 5.14 и Python 2.7 или 3.2.

JDK7 содержит обновления для классов Character, String и Pattern в поддержку Unicode 6.0.0. Это включает в себя поддержку свойств сценария Unicode и несколько улучшений Pattern, что позволяет ему соответствовать требованиям поддержки уровня 1 для регулярных выражений Unicode UTS # 18 . К ним относятся

  • Методы isupper и islower теперь корректно соответствуют свойствам в верхнем и нижнем регистре Юникода; ранее они неправильно применялись только к буквам, что не правильно, потому что оно пропускает Other_Uppercase и Other_Lowercase кодовые точки соответственно. Например, это несколько строчных кодов , которые не являются GC=Ll (строчными буквами), только выбранные образцы:

    % unichars -gs '\p{lowercase}' '\P{LL}'
    ◌ͅ  U+0345 GC=Mn SC=Inherited    COMBINING GREEK YPOGEGRAMMENI
    ͺ  U+037A GC=Lm SC=Greek        GREEK YPOGEGRAMMENI
    ˢ  U+02E2 GC=Lm SC=Latin        MODIFIER LETTER SMALL S
    ˣ  U+02E3 GC=Lm SC=Latin        MODIFIER LETTER SMALL X
    ᴬ  U+1D2C GC=Lm SC=Latin        MODIFIER LETTER CAPITAL A
    ᴮ  U+1D2E GC=Lm SC=Latin        MODIFIER LETTER CAPITAL B
    ᵂ  U+1D42 GC=Lm SC=Latin        MODIFIER LETTER CAPITAL W
    ᵃ  U+1D43 GC=Lm SC=Latin        MODIFIER LETTER SMALL A
    ᵇ  U+1D47 GC=Lm SC=Latin        MODIFIER LETTER SMALL B
    ₐ  U+2090 GC=Lm SC=Latin        LATIN SUBSCRIPT SMALL LETTER A
    ₑ  U+2091 GC=Lm SC=Latin        LATIN SUBSCRIPT SMALL LETTER E
    ⅰ  U+2170 GC=Nl SC=Latin        SMALL ROMAN NUMERAL ONE
    ⅱ  U+2171 GC=Nl SC=Latin        SMALL ROMAN NUMERAL TWO
    ⅲ  U+2172 GC=Nl SC=Latin        SMALL ROMAN NUMERAL THREE
    ⓐ  U+24D0 GC=So SC=Common       CIRCLED LATIN SMALL LETTER A
    ⓑ  U+24D1 GC=So SC=Common       CIRCLED LATIN SMALL LETTER B
    ⓒ  U+24D2 GC=So SC=Common       CIRCLED LATIN SMALL LETTER C
    
  • Буквенные тесты теперь верны в том смысле, что они используют Other_Alphabetic. Они сделали это неправильно до 1.7, что является проблемой.

  • Шаблон \x{HHHHH} убегает, так что вы можете встретить RL1.1; это позволяет переписать [?-?] (что не удается из-за проклятия UTF-16) как [\x{1D49C}-\x{1D4B5}]. JDK7 - это первая версия Java, которая полностью / правильно поддерживает не-BMP символы в этом отношении. Удивительно, но верно.

  • Дополнительные свойства для RL1.2, из которых свойство сценария является безусловно самым важным. Это позволяет вам написать \p{script=Greek}, например, сокращенно \p{Greek}.

  • Theновый UNICODE_CHARACTER_CLASSES флаг компиляции шаблона и соответствующий флаг встраиваемого шаблона "(?U)" для соответствия RL1.2a по свойствам совместимости.

Я, конечно, могу понять, почему вы хотите убедиться, что вызапуск Java с поддержкой Unicode 6.0.0, поскольку это также дает и другие преимущества.

6 голосов
/ 04 августа 2011

Это не тривиально, если вы ищете класс, чтобы сделать эту информацию доступной для вас.

Как правило, версии Unicode, поддерживаемые Java, меняются от одной основной спецификации к другой, и эта информация документируется в классе Character документации Java API (которая получена из спецификации языка Java). Однако вы не можете полагаться на спецификацию языка Java, поскольку каждая основная версия Java не обязательно должна иметь свою собственную версию Спецификации языка Java .

Следовательно, вам следует выполнить транслитерацию между версией Java, поддерживаемой JVM, и поддерживаемой версией Unicode как:

String specVersion = System.getProperty("java.specification.version");
if(specVersion.equals("1.7"))
    return "6.0";
else if(specVersion.equals("1.6"))
    return "4.0";
else if(specVersion.equals("1.5"))
    return "4.0";
else if(specVersion.equals("1.4"))
    return "3.0";
... and so on

Подробную информацию о поддерживаемых версиях можно получить из Спецификации языка Java. Ссылаясь на JSR 901 , который является спецификацией языка Java 7:

Платформа Java SE отслеживает спецификацию Unicode по мере ее развития. Точная версия Unicode, используемая данным выпуском, указана в документация класса Персонаж.

Версии Java язык программирования до 1.1 использовал Unicode версии 1.1.5. Обновления к более новым версиям стандарта Unicode, произошедшим в JDK 1.1 (для Unicode 2.0), JDK 1.1.7 (для Unicode 2.1), Java SE 1.4 (для Unicode 3.0) и Java SE 5.0 (для Unicode 4.0).

3 голосов
/ 04 августа 2011

Я не думаю, что это доступно через публичный API. Но это не подлежит изменению очень часто, поэтому вы можете получить версию спецификации:

System.getProperties().getProperty("java.specification.version")

и на основании этого выяснить версию Unicode.

java 1.0 -> Unicode 1.1
java 1.1 -> Unicode 2.0
java 1.2 -> Unicode 2.0
java 1.3 -> Unicode 2.0
java 1.4 -> Unicode 3.0
java 1.5 -> Unicode 4.0
java 1.6 -> Unicode 4.0
java 1.7 -> Unicode 6.0

Чтобы проверить это, вы можете увидеть JavaDoc для Символ класс.

3 голосов
/ 04 августа 2011

Версия Unicode определена в Спецификации языка Java §3.1 . Начиная с J2SE 5.0 поддерживается Unicode 4.0.

2 голосов
/ 28 марта 2018

Вот метод, который я использую, который должен быть совместим со всеми версиями Java> = 1.1.Он рассчитан на будущее только до Unicode 11.0, но его легко расширить, обратившись к файлу Unicode «DerivedAge.txt» (см. URL в комментариях к коду).соглашается с таблицей, скомпилированной Михалем Шрайером, и находит, что Java 8 поддерживает Unicode 6.2, а Java 9 поддерживает Unicode 8.0 (оба эти результата согласуются с документацией для их соответствующих Character классов).1006 * Код для обнаружения версий Unicode до 2.0 никогда не будет достигнут (с учетом требований Java 1.1 или выше) и присутствует только для полноты.

1 голос
/ 04 августа 2011

Поскольку поддерживаемая версия Unicode определяется версией Java, вы можете использовать эту информацию и вывести версию Unicode на основе того, что возвращает System.getProperty("java.version").

Я предполагаю, что вы хотите поддерживать только определенные версии Unicode или хотя бы некоторые минимальные. Я не эксперт по Unicode, но так как версии кажутся обратно совместимыми, вы можете определить версию Unicode как минимум 4.0, что означает, что поддерживаемая версия Java будет как минимум 5.0

...