Распечатывать шахматные символы с помощью UnicodeBlock?

Вместе с jdk12 появились шахматные символы (источник):

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. У меня джава 12.0.1.

Вопрос: Почему приведенный выше код ничего не печатает?

stackoverflow.com/questions/7665120/…
Steve Smith 14.05.2019 14:53

@StephenC Я использую Intellij, если я попытаюсь System.out.println("♔");, он напечатает символ, поэтому я считаю, что это строго связано с кодом.

Paul Lemarchand 14.05.2019 14:56

@SteveSmith Он не печатает прямоугольники, он вообще ничего не печатает. Также я хотел бы использовать UniblockCode для печати или, по крайней мере, понять, почему это не работает.

Paul Lemarchand 14.05.2019 14:57

Вы проверяете только первые 65536 символов, из них 1 114 112 символов Unicode.

JGNI 14.05.2019 15:03

@JGNI Я отредактировал код, но все еще не печатаю. Я тоже пробовал Character.MAX_VALUE.

Paul Lemarchand 14.05.2019 15:04

Вы установили кодировку на UTF-8?

Steve Smith 14.05.2019 15:16

@SteveSmith Если System.out.println("♔"); работает, то это не должно быть проблемой с кодировкой, или, может быть, что-то нужно указать в коде?

Paul Lemarchand 14.05.2019 15:20

Может быть, кодировка Windows не содержит всех символов Юникода? coderanch.com/t/538165/java/Отображение символов UniCode

Steve Smith 14.05.2019 15:23
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
8
8
391
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

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

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

char unicode = (char) i;

к этому:

int unicode = i;

Конечно, при замене char unicode = (char) i; на int unicode = i; вообще не нужны две разные переменные.

Holger 14.05.2019 17:41

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

Другие вопросы по теме