使用UnicodeBlock打印国际象棋符号吗?

时间:2019-05-14 12:51:00

标签: java unicode java-12

jdk12中,出现了国际象棋符号(source):

  

Unicode 11.0.0引入了JDK 12现在包含的以下新功能

     

[...] 4个块,用于以下现有脚本:

     
      
  • Georgian扩展

  •   
  • 玛雅数字

  •   
  • ndic Siyaq号码

  •   
  • 国际象棋符号

  •   

考虑到这一点,我尝试使用以下代码打印这些字符,以测试功能并稍后在小型国际象棋游戏中使用它们:

Character.UnicodeBlock block = Character.UnicodeBlock.CHESS_SYMBOLS;
for (int i = 0; i < 1114112; i++) {
    char unicode = (char) i;
    if(Character.UnicodeBlock.of(unicode) == block) {
        System.out.println(unicode);
    }
}

但是,它没有打印任何内容。如果我将CHESS_SYMBOLS替换为ARABIC,则该代码有效。我有Java 12.0.1。

问题:上面的代码为什么不打印任何内容?

2 个答案:

答案 0 :(得分:7)

“杂项符号”块中存在一些国际象棋符号字符,但是您正在检查另一个块中的16位char值。国际象棋符号块包含具有16位值的 zero 字符;它开始于U + 1FA00,结束于U + 1FA6F。

通过强制转换为char,可以将U + FFFF以上的所有值修整到最低16位;例如,如果i0x1fa60,则将其强制转换为char将其设置为0xfa60,这将阻止您的块检查成功。

要使您的代码正常工作,您需要停止所有代码点均为16位值的假设。您可以通过更改此方法来做到这一点:

char unicode = (char) i;

对此:

int unicode = i;

答案 1 :(得分:4)

不幸的是,Character.UnicodeBlock没有方法来告知块内代码点的起始值和结束值。在Unicode 11中,国际象棋符号块从U + 1FA00到U + 1FA6D。

Java使用UTF-16和surrogate pairs to represent characters over U+10000。在这种情况下,代码点U + 1FA00将表示为两个char值:U + D83E(高代理)和U + DE60(低代理)。

您应该使用Character.toChars()正确打印始终为int的代码点:

Character.UnicodeBlock block = Character.UnicodeBlock.CHESS_SYMBOLS;
for (int i = 0; i < 1114112; i++) {
    if (Character.UnicodeBlock.of(i).equals(block)) {
        System.out.println(Character.toChars(i));
    }
}