使用 UnicodeBlock 打印国际象棋符号?
Print chess symbols using UnicodeBlock?
随着 jdk12
,出现了国际象棋符号 (source):
Unicode 11.0.0 introduced the following new features that are now included in JDK 12
[...] 4 blocks for the following existing scripts:
Georgian Extended
Mayan Numerals
ndic Siyaq Numbers
Chess Symbols
考虑到这一点,我尝试使用以下代码打印这些字符,以测试功能并稍后在一个小国际象棋游戏中使用它们:
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.
问题:为什么上面的代码没有打印任何东西?
一些国际象棋符号字符存在于 Miscellaneous Symbols 块中,但您专门检查不同块中的 16 位 char
值。国际象棋符号块包含具有 16 位值的 零 个字符;它从 U+1FA00 开始,到 U+1FA6F 结束。
通过强制转换为 char
,您将把所有高于 U+FFFF 的值修剪到它们的最低 16 位;例如,如果 i
是 0x1fa60,将其转换为 char
将使它成为 0xfa60,这会阻止您的块检查成功。
要使您的代码正常工作,您需要停止假设所有代码点都是 16 位值。你可以通过改变这个来做到这一点:
char unicode = (char) i;
对此:
int unicode = i;
不幸的是,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));
}
}
随着 jdk12
,出现了国际象棋符号 (source):
Unicode 11.0.0 introduced the following new features that are now included in JDK 12
[...] 4 blocks for the following existing scripts:
Georgian Extended
Mayan Numerals
ndic Siyaq Numbers
Chess Symbols
考虑到这一点,我尝试使用以下代码打印这些字符,以测试功能并稍后在一个小国际象棋游戏中使用它们:
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.
问题:为什么上面的代码没有打印任何东西?
一些国际象棋符号字符存在于 Miscellaneous Symbols 块中,但您专门检查不同块中的 16 位 char
值。国际象棋符号块包含具有 16 位值的 零 个字符;它从 U+1FA00 开始,到 U+1FA6F 结束。
通过强制转换为 char
,您将把所有高于 U+FFFF 的值修剪到它们的最低 16 位;例如,如果 i
是 0x1fa60,将其转换为 char
将使它成为 0xfa60,这会阻止您的块检查成功。
要使您的代码正常工作,您需要停止假设所有代码点都是 16 位值。你可以通过改变这个来做到这一点:
char unicode = (char) i;
对此:
int unicode = i;
不幸的是,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));
}
}