Строка Java "привет" имеет 12 байтов, когда getBytes ("UTF-16")? - PullRequest
0 голосов
/ 01 декабря 2018

Я ожидал, что когда символ java хранится как «UTF-16», каждый символ использует 2 байта, поэтому «привет» должен занимать 10 байтов, но этот код:

String h = "hello";
System.out.println(new String(h.getBytes("UTF-16"), "UTF-16").length());
System.out.println(new String(h.getBytes("UTF-8"), "UTF-8").getBytes("UTF-16").length);

будет печатать«5 12»

Мой вопрос:

(1) Я ожидал, что первый println должен получить «10», как я уже упоминал.Но почему 5?

(2) Для второго println я пытаюсь получить для него байты сначала как «UTF-8», а затем как «UTF-16».Я полагаю, это также должно быть 10. Но на самом деле это 12.

Я использую MAC, и мой регион Гонконг.Не могли бы вы объяснить, что происходит в программе, и как на самом деле вышло «5 12»?

Большое спасибо!

Ответы [ 2 ]

0 голосов
/ 01 декабря 2018

Я ожидал, что первый println должен получить "10", как я уже говорил.Но почему 5?

Вы звоните length() на String, а не на byte[].Так что это даст вам длину строки в символах (по крайней мере, пока мы находимся в базовой многоязычной плоскости Unicode - это, к сожалению, ломается, когда у вас есть символы, которые нуждаются в кодировании переменной длины дажев UTF-16).

Если у вас есть строка, не имеет значения, какая кодировка использовалась для ее создания.length всегда дается в терминах символов.

Если вы преобразовали это в byte[] с использованием UTF-16, вы могли бы по праву ожидать 10 (для пяти символов, умноженных на два байта каждый) - что это на самом деле заканчивается 12 из-за байтаМарка заказа включена.

0 голосов
/ 01 декабря 2018

(1) Я ожидал, что первый println должен получить «10», как я упоминал.Но почему 5?

Вы берете 5-символьную строку, кодируете ее как байты, используя кодировку UTF-16.
Затем вы создаете новую строку, декодируя байты (правильно) из UTF-16., что дает вам новую строку, состоящую из ваших исходных 5 символов снова.

(2) Для второго println я пытаюсь получить для него сначала сначала «UTF-8», а затем «UTF».-16" .Я полагаю, это также должно быть 10. Но на самом деле это 12.

Эта часть кода:

    new String(h.getBytes("UTF-8"), "UTF-8")

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

Так эффективно вы делаете это:

    "hello".getBytes("UTF-16").length

Причиной дополнительных 2 байтов является то, что кодирование UTF-16 ставит BOM (метку порядка байтов) в качестве первой (2-байтовой) единицы кода.

Для получения дополнительной информации прочитайте часто задаваемые вопросы по Unicode на "UTF-8, UTF-16, UTF-32 & BOM" .

...