Страницы

Поиск по вопросам

четверг, 9 января 2020 г.

Переконвертация UTF8 <> 1251 и большая буква “И”

#java #utf_8 #encoding #cp1251


Берем строку "Игра!" и переводим в массив байт (1).
Создаём строку, из этого массива байт, но указываем "неверную" кодировку(2).
В итоге получаем строку с "поехавшей кодировкой"(utf8AsW1251 ).

Выполняем обратные действия(3). 
и видим что строка переконвертировалась нормально за исключение большой буквы "И".
Почему большая буква "И" отображается как �? ?

import java.nio.charset.Charset;

public class Main {
private static final Charset CS_1251 = Charset.forName("windows-1251");
private static final Charset CS_UTF8 = Charset.forName("UTF-8");

public static void main(String[] args) {
    String in = "Игра!";
    byte[] bytesUtf8 = in.getBytes(CS_UTF8);                    //(1)
    String utf8AsW1251 = new String(bytesUtf8, CS_1251);        //(2) 

    System.out.println("utf8 bytes as 1251: " + utf8AsW1251);   //utf8 bytes as 1251:
�гра!

    System.out.println(
            new String(utf8AsW1251.getBytes(CS_1251), CS_UTF8)  //(3) 
    );                                                          //�?гра!
}


}
    


Ответы

Ответ 1



– Доктор, когда я делаю так, у меня болит – Не делайте так Буква И кодируется в utf-8 как последовательность байтов 0xd0, 0x98 Код 0xd0 соответствует символу Р в кодировке cp1251, а вот код 0x98 не соответствует никакому символу, он просто отсутствует в кодировке, поэтому вместо несуществующего символа будет подставлен заменяющий. Получится строка Р�. Cимвол � тоже отсутсвует в cp1251, поэтому при повторном кодировании будет заменен на ? (с кодом 0x3f), получаем последовательность байтов 0xd0, 0x3f. При декодировании сталкиваемся еще с одной проблемой: последовательность 0xd0, 0x3f недопустима в utf-8, поэтому теперь уже вместо 0xd0 будет подставлен заменяющий символ, в итоге получается строка �? С остальными буквами такого может и не произойти, но это не значит, что подобные манипуляции всегда будут приводить к правильному результату Й → 0xd0, 0x99 → Р™ → 0xd0, 0x99 → Й

Комментариев нет:

Отправить комментарий