如何在Java中以编程方式识别哪个Unicode版本支持?

Rom*_*gan 7 java unicode jvm java-7

由于Java代码可以在任何Java VM中运行,我想知道如何以编程方式识别支持哪种Unicode版本?

tch*_*ist 7

最简单的方法,但我想到的最糟糕的方法是选择一个新的每个Unicode版本的代码点,并检查其Character属性.或者您可以使用正则表达式检查其常规类别.以下是一些选定的代码点:

  • 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
    
    Run Code Online (Sandbox Code Playgroud)
  • Unicode 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
    
    Run Code Online (Sandbox Code Playgroud)
  • Unicode 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
    
    Run Code Online (Sandbox Code Playgroud)
  • Unicode 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
    
    Run Code Online (Sandbox Code Playgroud)

我已经包含了常规类别和脚本属性,但您只能检查JDK7中的脚本,这是第一个支持该脚本的Java版本.

我通过命令行运行这样的命令找到了这些代码点:

% unichars -gs '\p{Age=5.1}'
% unichars -gs '\p{Lu}' '\p{Age=5.0}'
Run Code Online (Sandbox Code Playgroud)

那是unichars计划.它只会在您运行的Perl版本支持的任何UCD版本中找到Unicode字符数据库中支持的属性.

我也喜欢我的输出排序,所以我倾向于运行

 % unichars -gs '\p{Alphabetic}' '\p{Age=6.0}' | ucsort | less -r
Run Code Online (Sandbox Code Playgroud)

这是 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
Run Code Online (Sandbox Code Playgroud)

这表明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
Run Code Online (Sandbox Code Playgroud)

要找出特定代码点的年龄,请运行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
Run Code Online (Sandbox Code Playgroud)

我所有的Unicode工具在可用的Unicode ::厮打软件包,其中包括单字符,uninames,uniquote,ucsort,等等.

Java 1.7改进

JDK7在简化一些Unicode事务方面走了很长的路.我在OSCON Unicode支持Shootout演讲结束时谈到了这一点.我曾想过将一个语言集合在一起,这些语言支持哪些版本的Unicode在哪些版本的语言版本中,但最终废弃它以告诉人们只获取每种语言的最新版本.例如,我知道Java 1.7,Perl 5.14和Python 2.7或3.2支持Unicode 6.0.0.

JDK7包含类的更新Character,String以及Pattern在支持Unicode 6.0.0.这包括对Unicode脚本属性的支持,以及一些增强功能,Pattern使其能够满足Unicode UTS#18正则表达式的 1级支持要求.这些包括

  • isupperislower方法现在正确对应的Unicode大写和小写性能; 以前他们只误用字母,这是不正确的,因为它遗漏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
    
    Run Code Online (Sandbox Code Playgroud)
  • 字母测试现在正确使用Other_Alphabetic.他们在1.7之前做错了,这是一个问题.

  • \x{HHHHH}模式逃生因此可满足RL1.1; 这可以让你重写[-](由于UTF-16诅咒而失败)[\x{1D49C}-\x{1D4B5}].JDK7是第一个在这方面完全/正确支持非BMP字符的Java版本.惊人但真实.

  • RL1.2的更多属性,其中脚本属性是最重要的.这可以让你写\p{script=Greek}例如,缩写为\p{Greek}.

  • UNICODE_CHARACTER_CLASSES模式编译标志和相应的模式嵌入标志,"(?U)"以满足兼容性属性RL1.2a.

我当然可以理解你为什么要确保你运行支持Unicode 6.0.0的Java,因为它带来了所有其他好处.


Vin*_*lds 6

如果您正在寻找一个可以向您提供此信息的课程,这并非易事.

通常,Java支持的Unicode版本会从一个主要规范更改为另一个主要规范,并且此信息记录在Java API文档的Character类中(源自Java语言规范).但是,您不能依赖Java语言规范,因为Java的每个主要版本都不需要拥有自己的Java语言规范版本.

因此,您应该在JVM支持的Java版本和支持的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
Run Code Online (Sandbox Code Playgroud)

支持的版本的详细信息可以从Java语言规范中获得.从JSR 901引用,这是Java 7的语言规范:

Java SE平台随着它的发展跟踪Unicode规范.给定版本使用的Unicode的精确版本在类Character的文档中指定.

1.1之前的Java编程语言的版本使用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).