Неправильные байты из кодировки UTF-16 - PullRequest
5 голосов
/ 26 марта 2019

У меня есть символ '?'. Значение Юникода равно U + 1F62D , двоичный эквивалент - 11111011000101101 . Теперь я хочу преобразовать этот символ в байтовый массив. Мои шаги

1) Поскольку двоичное представление больше 2 байтов, я использую 4 байта

XXXXXXXX XXXXXXX1 11110110 00101101

2) Теперь я заменяю все «X» на «0»

00000000 00000001 11110110 00101101

3) Десятичные эквиваленты

00000000 (0) 00000001 (1) 11110110 (-10) 00101101 (45)

Это мой код

@Test
    public void testUtf16With4Bytes() throws Exception {
        assertThat(
                new String(
                        new byte[]{0,1,-10,45},
                        StandardCharsets.UTF_16BE
                ),
                is("?")
        );
    }

Это вывод

ava.lang.AssertionError: 
Expected: is "?"
     but: was ""

Что я пропустил?

1 Ответ

6 голосов
/ 26 марта 2019

Вам не хватает того, что некоторые символы UTF хранятся в виде суррогатных пар :

В UTF-16 символы в диапазонах U + 0000 — U + D7FF и U + E000—U + FFFD хранятся как единая 16-битная единица.Не-BMP символы (диапазон U + 10000 - U + 10FFFF) сохраняются как «суррогатные пары», две 16-битные единицы: старший суррогат (в диапазоне U + D800 - U + DBFF), за которым следует низкий суррогат (в диапазоне U+ DC00-U + DFFF).Одиночный суррогатный символ недопустим в UTF-16, суррогатные символы всегда пишутся парами (высокий, затем низкий).

символ is равен U+1F62D, поэтому он попадает в диапазон U+10000—U+10FFFF.Он представлен суррогатной парой U+D83D U+DE2D, так как byte[] это будет [-40, 61, -34, 45].

...