Распечатать шахматные символы с помощью UnicodeBlock? - PullRequest
7 голосов
/ 14 мая 2019

С jdk12 пришли символы шахмат ( источник ):

Unicode 11.0.0 представил следующие новые функции, которые теперь включены в JDK 12

[...] 4 блока для следующих существующих сценариев:

  • Грузинский расширенный

  • Числа майя

  • ndic Siyaq Numbers

  • Шахматные символы

Имея это в виду, я попытался напечатать эти символы сследующий код, чтобы проверить функциональность и использовать их позже в маленькой шахматной игре:

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 ]

7 голосов
/ 14 мая 2019

Некоторые символы шахматных символов существуют в блоке Разные символы, но вы специально проверяете 16-битные значения char в другом блоке. Блок Шахматные символы содержит ноль символов с 16-битными значениями; начинается с U + 1FA00 и заканчивается на U + 1FA6F.

При значении char вы обрезаете все значения выше U + FFFF до их младших 16 битов; например, если i равно 0x1fa60 , приведение к char сделает его 0xfa60, что препятствует успешной проверке блока.

Чтобы ваш код работал, вам нужно прекратить предполагать, что все кодовые точки являются 16-битными значениями. Вы можете сделать это, изменив это:

char unicode = (char) i;

к этому:

int unicode = i;
4 голосов
/ 14 мая 2019

К сожалению, 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));
    }
}
...