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

如何在Java中以编程方式确定支持哪个Unicode版本?,unicode,jvm,java,java-7,Unicode,Jvm,Java,Java 7,由于Java代码可以在任何Java虚拟机中运行,我想知道如何以编程方式确定支持哪个Unicode版本?Unicode版本是在中定义的。因为J2SE 5.0支持Unicode 4.0 引述: JDK1.1之前的Java编程语言版本使用Unicode 1.1.5。在JDK1.1(到Unicode 2.0)、JDK1.1.7(到Unicode 2.1)、JavaSE1.4(到Unicode 3.0)、JavaSE5.0(到Unicode 4.0)、JavaSE7(到Unicode 6.0)、JavaS

由于Java代码可以在任何Java虚拟机中运行,我想知道如何以编程方式确定支持哪个Unicode版本?

Unicode版本是在中定义的。因为J2SE 5.0支持Unicode 4.0

引述:

JDK1.1之前的Java编程语言版本使用Unicode 1.1.5。在JDK1.1(到Unicode 2.0)、JDK1.1.7(到Unicode 2.1)、JavaSE1.4(到Unicode 3.0)、JavaSE5.0(到Unicode 4.0)、JavaSE7(到Unicode 6.0)、JavaSE8(到Unicode 6.2)、JavaSE9(到Unicode 8.0)、JavaSE11(到Unicode 10.0)、JavaSE12(到Unicode 11.0)和JavaSE13中,出现了更新版本的Unicode标准升级(至Unicode 12.1)


由于受支持的unicode版本是由Java版本定义的,因此您可以使用该信息并根据
System.getProperty(“Java.version”)
返回的内容推断unicode版本


我假设您只想支持特定的unicode版本,或者至少支持一些最低版本。我不是unicode专家,但由于这些版本似乎是向后兼容的,您可以将unicode版本定义为至少4.0,这意味着支持的Java版本至少是5.0。如果您正在寻找一个类来实现您是否可以获得这些信息

通常,Java支持的Unicode版本会从一个主要规范更改为另一个规范,并且这些信息记录在Java API文档(源自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
支持版本的详细信息可以从Java语言规范中获得。参考Java 7的语言规范:

JavaSE平台随着Unicode规范的发展而跟踪它。 中指定了给定版本使用的Unicode的精确版本 类字符的文档

Java的版本 1.1之前的编程语言使用Unicode版本1.1.5。升级 更新版本的Unicode标准出现在JDK 1.1中(到 Unicode 2.0)、JDK1.1.7(到Unicode 2.1)、JavaSE1.4(到Unicode 3.0)和JavaSE5.0(到Unicode 4.0)


我不认为它可以通过公共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 for类。

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

  • 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
    
我已经包括了general类别和script属性,尽管您只能在JDK7中检查脚本,JDK7是第一个支持该属性的Java版本

我通过从命令行运行如下命令找到了这些代码点:

% unichars -gs '\p{Age=5.1}'
% unichars -gs '\p{Lu}' '\p{Age=5.0}'
这里是程序。它将只查找Unicode字符数据库中支持的属性,无论您运行的Perl版本支持哪个UCD版本

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

 % unichars -gs '\p{Alphabetic}' '\p{Age=6.0}' | ucsort | less -r
这就是程序,它根据Unicode排序算法对文本进行排序

然而,与Java不同的是,在Perl中,这很容易找到 从命令行运行此命令(是的,还有一个程序员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 10424
U+10424 ‹Here's a method I use, which should be compatible with all versions of Java >= 1.1. It's future-proofed only up to Unicode 13.0, but is easily extended by referring to the Unicode "DerivedAge.txt" file (see the URL in the code comments).

As far back as I've tested, it agrees with the table Michał Šrajer compiled, and it correctly determines Java 8 supports Unicode 6.2, Java 9 supports Unicode 8.0, and Java 13 supports Unicode 12.1.

/**
 * Gets the version of <a href="https://www.unicode.org/versions/enumeratedversions.html">
 * Unicode</a> supported by the {@link java.lang.Character} class. The return value represents
 * the major and minor version numbers (in low-order octets 1 and 0, respectively). The "update"
 * version number is not represented, because "update" versions do not add new code-points, 
 * and new code-points are the basis of version detection in this method.
 * <p>
 * This version number be can converted to a representation suitable for human interfaces with 
 * code such as <code>(version >> 8) + "." + (version & 0xFF)</code> or 
 * <code>System.out.printf("Unicode version: %d.%d%n", version >> 8, version & 0xFF)</code>.
 * <p>
 * This method is compatible with Java versions >= 1.1.
 *
 * @return Unicode version number, with the major version number in low-order octet 1 and the 
 *         minor version number in low-order octet 0
 */
public static int getUnicodeVersion() {

/*  Version determination is based on testing support for the first new 
    code-point added by each version of Unicode. (See 
    <https://www.unicode.org/Public/UCD/latest/ucd/DerivedAge.txt>.)

    Regarding omission of the update version number, the document "Unicode 
    Standard Annex #44, Unicode Character Database" revision 21 (from 
    Unicode 11.0.0 draft 1) states:

    "Formally, the Age property is a catalog property whose enumerated 
    values correspond to a list of tuples consisting of a major version 
    integer and a minor version integer. The major version is a positive 
    integer constrained to the range 1..255. The minor version is a non-
    negative integer constrained to the range 0..255. These range limit-
    ations are specified so that implementations can be guaranteed that 
    all valid, assigned Age values can be represented in a sequence of two 
    unsigned bytes. A third value corresponding to the Unicode update 
    version is not required, because new characters are never assigned in 
    update versions of the standard."

    See <https://www.unicode.org/reports/tr44/tr44-21.html#Character_Age>
    for further details.
*/
//  Preliminary Unicode 13.0 data obtained from <https://www.unicode.org/Public/13.0.0/ucd/DerivedAge-13.0.0d1.txt>.

    if (Character.getType('\u08Be') != Character.UNASSIGNED)
        return 0xD00;    //  13.0, March 2020.

    if (Character.getType('\u32FF') != Character.UNASSIGNED)
        return 0xC01;    //  12.1, May 2019.

    if (Character.getType('\u0C77') != Character.UNASSIGNED)
        return 0xC00;    //  12.0, March 2019.

    if (Character.getType('\u0560') != Character.UNASSIGNED)
        return 0xB00;    //  11.0, June 2018.

    if (Character.getType('\u0860') != Character.UNASSIGNED)
        return 0xA00;    //  10.0, June 2017.

    if (Character.getType('\u08b6') != Character.UNASSIGNED)
        return 0x900;     //  9.0, June 2016.

    if (Character.getType('\u08b3') != Character.UNASSIGNED)
        return 0x800;     //  8.0, June 2015.

    if (Character.getType('\u037f') != Character.UNASSIGNED)
        return 0x700;     //  7.0, June 2014.

    if (Character.getType('\u061c') != Character.UNASSIGNED)
        return 0x603;     //  6.3, September 2013.

    if (Character.getType('\u20ba') != Character.UNASSIGNED)
        return 0x602;     //  6.2, September 2012.

    if (Character.getType('\u058f') != Character.UNASSIGNED)
        return 0x601;     //  6.1, January 2012.

    if (Character.getType('\u0526') != Character.UNASSIGNED)
        return 0x600;     //  6.0, October 2010.

    if (Character.getType('\u0524') != Character.UNASSIGNED)
        return 0x502;     //  5.2, October 2009.

    if (Character.getType('\u0370') != Character.UNASSIGNED)
        return 0x501;     //  5.1, March 2008.

    if (Character.getType('\u0242') != Character.UNASSIGNED)
        return 0x500;     //  5.0, July 2006.

    if (Character.getType('\u0237') != Character.UNASSIGNED)
        return 0x401;     //  4.1, March 2005.

    if (Character.getType('\u0221') != Character.UNASSIGNED)
        return 0x400;     //  4.0, April 2003.

    if (Character.getType('\u0220') != Character.UNASSIGNED)
        return 0x302;     //  3.2, March 2002.

    if (Character.getType('\u03f4') != Character.UNASSIGNED)
        return 0x301;     //  3.1, March 2001.

    if (Character.getType('\u01f6') != Character.UNASSIGNED)
        return 0x300;     //  3.0, September 1999.

    if (Character.getType('\u20ac') != Character.UNASSIGNED)
        return 0x201;     //  2.1, May 1998.

    if (Character.getType('\u0591') != Character.UNASSIGNED)
        return 0x200;     //  2.0, July 1996.

    if (Character.getType('\u0000') != Character.UNASSIGNED)
        return 0x101;     //  1.1, June 1993.

    return 0x100;         //  1.0
}
%uniprops-a 10424

U+10424嫀这里有一个我使用的方法,它应该与Java>=1.1的所有版本兼容。它的未来版本仅限于Unicode 13.0,但通过引用Unicode“DerivedAge.txt”文件(参见代码注释中的URL)可以轻松扩展

早在我测试的时候,它就与编译的表MichałŠrajer一致,并且它正确地确定了Java8支持Unicode 6.2,Java9支持Unicode 8.0,Java13支持Unicode 12.1


检测2.0之前的Unicode版本的代码永远无法达到(考虑到Java 1.1或更高的要求),并仅为完整性而提供。

支持何处?源代码?字符串处理?我建议澄清要参考的问题,您真正谈论的是unicode版本,而不是字符集。.unicode 4.0支持仅限于Java平台的5.0和6.0版本。@Vinet:仅支持Unico早在2003年,de 4就已经成为一个主要的负担。我很惊讶Java 1.6不支持Unicode 5.0;如果看看发布日期,它本可以支持Unicode 5.0。这意味着人们必须等待很长时间才能获得当前Unicode规范的支持。这几乎让你觉得有人忘记了它。@tchrist:我想你必须使用BigDecim尽管如此,除非您希望Java 1.0支持Unicode 1.1000000000000088817841970012523233890533447265625:-)过度杀伤力?实际上,我之所以省略双精度、浮点和数字表示,是因为版本号不必是小数。以Unicode支持的第一个版本为例-1.1.5将不会解析为数字格式。@Vinet I