在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。
问题:上面的代码为什么不打印任何内容?
答案 0 :(得分:7)
“杂项符号”块中存在一些国际象棋符号字符,但是您正在检查另一个块中的16位char
值。国际象棋符号块包含具有16位值的 zero 字符;它开始于U + 1FA00,结束于U + 1FA6F。
通过强制转换为char
,可以将U + FFFF以上的所有值修整到最低16位;例如,如果i
为0x1fa60,则将其强制转换为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));
}
}