Java - что такое символы, кодовые точки и суррогаты? Какая между ними разница?
Я пытаюсь найти объяснение терминов "символ", "кодовая точка" и "суррогат", и хотя эти термины не ограничиваются Java, если есть какие-либо языковые различия, я хотел бы получить объяснение, как это относится к Java.
Я нашел некоторую информацию о различиях между символами и кодовыми точками, символами, отображаемыми для пользователей-людей, и кодовыми точками, кодирующими значение этого конкретного символа, но я понятия не имею о суррогаты. Что такое суррогаты и чем они отличаются от символов и кодовых точек? Есть ли у меня правильные определения символов и кодовых точек?
на другой поток о переходе через строку как массив символов, конкретный комментарий, который вызвал этот вопрос, был " обратите внимание, что этот метод дает вам символы, а не кодовые точки, что означает, что вы можете получить суррогаты."Я действительно не понял, и вместо того, чтобы создавать длинную серию комментариев Вопрос 5-летней давности я подумал, что было бы лучше попросить разъяснений в новом вопросе.
3 ответов
чтобы представить текст в компьютерах, вам нужно решить две вещи: во-первых, вы должны сопоставить символы с числами, затем вы должны представить последовательность этих чисел с байтами.
на код - это число, которое идентифицирует символ. Два известных стандарта присвоения чисел символам-ASCII и Unicode. ASCII определяет 128 символов. Unicode в настоящее время определяет 109384 символа, это больше, чем 216.
кроме того, ASCII указывает, что номерные серии представлены по одному байту на число, в то время как Unicode указывает несколько возможностей, таких как UTF-8, UTF-16 и UTF-32.
когда вы пытаетесь использовать кодировку, которая использует меньше бит на символ, чем необходимо для представления всех возможных значений (например, UTF-16, который использует 16 бит), вам нужно некоторое обходное решение.
таким образом, суррогаты 16-разрядные значения, которые указывают символы, которые не вписываются в один двухбайтовый значение.
Java использует UTF-16.
в частности, a char
(символ)-это беззнаковое двухбайтовое значение, содержащее значение UTF-16.
Если вы хотите узнать больше о Java и Unicode, я могу рекомендовать эту рассылку: Часть 1, Часть 2
вы можете найти краткое объяснение в Javadoc для класса java.ленг.Характер:
Отображение Символов Юникода
на
char
тип данных (и, следовательно, значение, котороеCharacter
объект инкапсулируется) основаны на исходной спецификации Unicode, которая определяла символы как 16-разрядные объекты фиксированной ширины. С тех пор стандарт Unicode был изменен, чтобы разрешить символы, представление которых требуется более 16 бит. Диапазон legal коды теперьU+0000
toU+10FFFF
, известного как скалярное значение Юникода. [..]набор символов
U+0000
toU+FFFF
иногда называют основной многоязычный самолет (BMP). Символы, кодовые точки которых большеU+FFFF
называют дополнительные символы. Платформа Java использует представление UTF-16 вchar
массивы и в theString
иStringBuffer
классы. В этом представлении, дополнительные символы представлены в виде парыchar
значения, первые из высокого суррогаты диапазон, (\uD800 - \uDBFF), второй от низкий-суррогаты диапазон (\uDC00 - \uDFFF).
другими словами:
A код обычно представляет собой один символ. Первоначально значения типа char
соответствует точно кодовые точки Юникода. Эта кодировка также была известна как UCS-2.
по этой причине char
был определен как 16-разрядный тип. Однако в настоящее время существует более 2^16 символы в Unicode. Чтобы поддержать все набор символов кодировка была изменена с фиксированной длиной кодировка UCS-2 к кодировке переменной длины UTF-16. В этой кодировке, каждая кодовая точка представлена одним char
и два char
s. В последнем случае два символа называются a суррогатная пара.
UTF-16 был определен таким образом, что нет никакой разницы между текстом, закодированным с UTF-16 и UCS-2, если все кодовые точки ниже 2^14. Это значит,char
может использоваться для представления некоторых, но не всех символы. Если a символ не может быть представлен в пределах одного char
термин char
вводит в заблуждение, потому что это просто используется как 16-битное слово.
кодовые точки обычно относятся к кодовым точкам Unicode. В глоссарии Unicode говорится следующее:
Codepoint (1): любое значение в кодовом пространстве Юникода; то есть диапазон целых чисел от 0 до 10FFFF16.
в Java, символ (char
) - 16-битное значение без знака; i.e 0 - FFFF.
Как вы можете видеть, есть больше кодовых точек Unicode, которые могут быть представлены как символы Java. И все же Java должна иметь возможность представлять текст, использующий все допустимые кодовые точки Unicode.
способ, которым Java имеет дело с этим, - представлять кодовые точки, которые больше, чем FFFF, как пара символов (кодовых единиц); т. е. a суррогатная пара. Эти кодирование кодовая точка Unicode, которая больше FFFF как пара 16-битных значений. Это использует тот факт, что поддиапазон кодового пространства Unicode (т. е. от D800 до U+DFFF) зарезервирован для представления суррогатных пар. Техническая деталь are здесь.
правильным термином для кодировки, которую использует Java, является форма кодирования UTF-16.
другой термин, который вы можете увидеть, это код который является минимальной репрезентативной единицей, используемой в определенной кодировке. В UTF-16 кодовая единица составляет 16 бит