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

8

随着jdk12的发布,国际象棋符号也得以加入其中(来源):

Unicode 11.0.0引入了以下新功能,现在已包含在JDK 12中:

[...] 对以下现有脚本的4个块进行了扩展:

  • 格鲁吉亚扩展

  • 玛雅数字

  • 阿拉伯数字

  • 国际象棋符号

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

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);
    }
}

然而,它并没有打印任何东西。如果我用ARABIC代替CHESS_SYMBOLS,则代码可以正常运行。我使用的是Java 12.0.1。
问题:为什么上述代码没有打印任何内容?

5
https://dev59.com/5VvUa4cB1Zd3GeqPyfFv - Steve Smith
@SteveSmith 它并不是在打印矩形,而是根本没有打印任何东西。另外我想使用UniblockCode来进行打印,或者至少了解为什么它不能工作。 - Paul Lemarchand
你只检查了前65536个字符,而实际上Unicode字符总数为1,114,112个。 - JGNI
你设置了字符集为UTF-8吗? - Steve Smith
也许Windows字符集并不包含所有Unicode字符? https://coderanch.com/t/538165/java/Displaying-UniCode-characters - Steve Smith
显示剩余3条评论
2个回答

8

一些象棋符号字符存在于杂项符号块中,但您正在特定地检查不同块中的16位char值。象棋符号块不包含任何具有16位值的字符;它从U+1FA00开始,到U+1FA6F结束。

通过将其转换为char,您可以将所有高于U+FFFF的值裁剪为它们最低的16位;例如,如果i0x1fa60,将其转换为char将使其成为0xfa60,这会阻止您的块检查成功。

要使您的代码正常工作,您需要停止假设所有代码点都是16位值。您可以通过更改以下内容来实现:

char unicode = (char) i;

转换为:

int unicode = i;

3
当将代码中的 char unicode = (char) i; 改为 int unicode = i; 时,根本不需要两个不同的变量。 - Holger

4

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

Java使用UTF-16和代理对来表示超过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));
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接