Почему декодирование и кодирование строк в java не всегда симметрично?

Меня смущает декодирование и кодирование в Java String.

Теперь у меня есть строковая переменная «中国», что означает Китай на китайском языке, которая содержится в китайской собственной кодировке GB2312, а также в Unicode.

Так в чем разница между следующими ??

val f = "中国"

println(new String(f.getBytes("GB2312"),"GB2312"))

println(new String((new  String(f.getBytes("GB2312"),"UTF8")).getBytes("UTF8"),"GB2312") ) 
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
114
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Он ведет себя так, потому что вывод new String(x, "UTF8").getBytes("UTF8") будет только x, если x на самом деле является допустимым байтовым представлением строки UTF-8. В противном случае согласно javadoc для String

This method always replaces malformed-input and unmappable-character sequences with this charset's default replacement string.

Символом по умолчанию для UTF-8 является � (битовое представление 11101111 10111111 10111101). f.getBytes("GB2312") возвращает следующую последовательность битов: 11010110 11010000 10111001 11111010. Как в одном недопустимом символе, за которым следует 11010000 10111001 или й, а затем еще один недопустимый символ. Выход new String(f.getBytes("GB2312"),"UTF8") для этого - или преобразован в двоичную форму, 11101111 10111111 10111101 11010000 10111001 11101111 10111111 10111101.

11010110 и 11111010 недопустимы, потому что любая последовательность байтов, начинающаяся с байта формы 11xxxxxx, должна сопровождаться одним или несколькими байтами в форме 10xxxxxx (точное число зависит от количества 1 в начале первого числа). См. Википедия для получения дополнительных сведений о формате UTF-8.

Просто new String(s.getBytes("UTF8"),"GB2312") ) не делает того, что вы думаете. (Я не знаю, что вы думаете, но ничего хорошего из этого не выйдет, так что я предполагаю.)

Это означает: закодируйте текст из строки с помощью UTF-8, затем возьмите эти байты и декодируйте их, как если бы они были текстом, закодированным с помощью GB2313.

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