Java utf8 encoding - char, типы строк
public class UTF8 {
public static void main(String[] args){
String s = "ヨ"; //0xFF6E
System.out.println(s.getBytes().length);//length of the string
System.out.println(s.charAt(0));//first character in the string
}
}
выход:
3
ヨ
Пожалуйста, помогите мне понять это. Попытка понять, как работает кодировка utf8 в java.
Согласно определению java doc char
char: тип данных char - это один 16-разрядный символ Юникода.
Означает ли это, что char тип в java может поддерживать только те символы unicode, которые могут быть представлены с 2 байтами и не более?
В приведенной выше программе количество байтов, выделенных для этой строки, равно 3, но в третьей строке, которая возвращает первый символ (2 байта в java), может содержать символ длиной 3 байта?
действительно запутался здесь?
Любые хорошие ссылки на эту концепцию в java/general были бы действительно оценены.
Ответы
Ответ 1
Ничто в вашем примере кода напрямую не использует UTF-8. Строки Java кодируются в памяти с использованием UTF-16. Кодовые страницы Unicode, которые не помещаются в один 16-разрядный char, будут закодированы с использованием пары 2- char, известной как суррогатная пара.
Если вы не передадите значение параметра String.getBytes()
, он возвращает массив байтов, который содержит содержимое String
, закодированное с использованием базовой кодировки по умолчанию для ОС. Если вы хотите обеспечить кодированный UTF-8 массив, вам нужно вместо этого использовать getBytes("UTF-8")
.
Вызов String.charAt()
возвращает исходный кодированный UTF-16 char только из памяти в строковой памяти.
Итак, в вашем примере символ Unicode ョ
хранится в хранилище String
в памяти с использованием двух байтов, кодированных UTF-16 (0x6E 0xFF
или 0xFF 0x6E
в зависимости от endian), но сохраняется в массиве байтов из getBytes()
с использованием трех байтов, которые кодируются с использованием любой кодировки по умолчанию для ОС.
В UTF-8 этот символ Юникода также использует 3 байта (0xEF 0xBD 0xAE
).
Ответ 2
String.getBytes()
возвращает байты, используя кодировку символов по умолчанию платформы, которая не обязательно соответствует внутреннему представлению.
Лучше никогда не использовать этот метод в большинстве случаев, потому что в большинстве случаев не имеет смысла полагаться на кодировку по умолчанию платформы. Вместо этого используйте String.getBytes(String charsetName)
и явным образом задайте набор символов, который должен использоваться для кодирования вашей строки в байтах.
Ответ 3
UTF-8 - это кодирование с переменной длиной слова, которое использует только один байт для символов ASCII (значения от 0 до 127) и два, три (или даже больше) байта для других символов Unicode.
Это связано с тем, что старший бит байта используется для указания "это многобайтовая последовательность", поэтому один бит на 8 не используется для фактического представления "реальных" данных (код char), но для отметки байт.
Итак, несмотря на то, что Java использует 2 байта в ram для каждого char, когда символы "сериализуются" с использованием UTF-8, они могут генерировать один, два или три байта в результирующем массиве байтов, как UTF-8 кодирование работает.
Ответ 4
Так Java представляет символы: http://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#unicode