由于Java代码可以在任何Java VM中运行,我想知道如何以编程方式识别支持哪种Unicode版本?
答案 0 :(得分: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
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
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
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
我已经包含了常规类别和脚本属性,但您只能检查JDK7中的脚本,这是第一个支持该脚本的Java版本。
我通过命令行运行这样的命令来找到这些代码点:
% unichars -gs '\p{Age=5.1}'
% unichars -gs '\p{Lu}' '\p{Age=5.0}'
那是unichars计划。它只会在您运行的Perl版本支持的任何UCD版本中找到Unicode字符数据库中支持的属性。
我也喜欢我的输出排序,所以我倾向于运行
% 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::Tussle捆绑包中提供了我的所有Unicode工具,包括unichars,uninames,uniquote,ucsort等等。
JDK7在使一些Unicode事物变得更容易方面走了很长的路。我在OSCON Unicode支持Shootout演讲结束时谈到了这一点。我曾想过将一个语言集合在一起,这些语言支持哪些版本的Unicode在哪些版本的语言版本中,但最终废弃它以告诉人们只获取每种语言的最新版本。例如,我知道Java 1.7,Perl 5.14和Python 2.7或3.2支持Unicode 6.0.0。
JDK7包含支持Unicode 6.0.0的类Character
,String
和Pattern
的更新。这包括对Unicode脚本属性的支持,以及Pattern
的一些增强功能,以使其满足Unicode UTS#18 Regular Expressions的1级支持要求。其中包括
isupper
和islower
方法现在正确对应于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
字母测试现在正确,因为它们使用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,因为这也带来了所有其他好处。
答案 1 :(得分:6)
如果您正在寻找一个可以向您提供此信息的课程,这不是一件轻而易举的事。
通常,Java支持的Unicode版本会从一个主要规范更改为另一个主要规范,并且此信息记录在Java API文档的Character类中(源自Java语言规范)。但是,您不能像每个major version of Java need not have its own version of the Java Language Specification那样依赖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
支持的版本的详细信息可以从Java语言规范中获得。引自JSR 901这是Java 7的语言规范:
Java SE平台随着它的发展跟踪Unicode规范。 给定版本使用的Unicode的精确版本在中指定 类字符的文档。
Java的版本 1.1之前的编程语言使用Unicode版本1.1.5。升级 在JDK 1.1中发生了更新版本的Unicode标准 Unicode 2.0),JDK 1.1.7(到Unicode 2.1),Java SE 1.4(到Unicode 3.0)和Java SE 5.0(到Unicode 4.0)。
答案 2 :(得分:3)
Unicode版本在Java Language Specification §3.1中定义。由于支持J2SE 5.0 Unicode 4.0。
答案 3 :(得分:3)
我不认为它可以通过公共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
要验证它,您可以看到Character类的JavaDoc。
答案 4 :(得分:2)
这是我使用的方法,它应与所有版本的Java> = 1.1兼容。它的未来版本仅限于Unicode 11.0,但可以通过引用Unicode“DerivedAge.txt”文件轻松扩展(请参阅代码注释中的URL)。
早在我可以测试的时候,它同意MichałŠrajer编译的表,并且它发现Java 8支持Unicode 6.2,而Java 9支持Unicode 8.0(这两个结果都与它们各自的文档一致{ {1}}类)。
Character
永远不会达到检测2.0之前的Unicode版本的代码(考虑到Java 1.1或更高版本的要求),并且仅为了完整性而存在。
答案 5 :(得分:1)
由于支持的unicode版本是由Java版本定义的,因此您可以使用该信息并根据System.getProperty("java.version")
返回的内容推断unicode版本。
我假设您只想支持特定的unicode版本或至少支持一些最小版本。我不是unicode专家,但由于版本似乎是向后兼容的,你可能会将unicode版本定义为至少4.0,这意味着支持的Java版本将至少为5.0