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 to U+10FFFF, известного как скалярное значение Юникода. [..]

набор символов U+0000 to U+FFFF иногда называют основной многоязычный самолет (BMP). Символы, кодовые точки которых больше U+FFFF называют дополнительные символы. Платформа Java использует представление UTF-16 в char массивы и в the String и StringBuffer классы. В этом представлении, дополнительные символы представлены в виде пары char значения, первые из высокого суррогаты диапазон, (\uD800 - \uDBFF), второй от низкий-суррогаты диапазон (\uDC00 - \uDFFF).

другими словами:

A код обычно представляет собой один символ. Первоначально значения типа char соответствует точно кодовые точки Юникода. Эта кодировка также была известна как UCS-2.

по этой причине char был определен как 16-разрядный тип. Однако в настоящее время существует более 2^16 символы в Unicode. Чтобы поддержать все набор символов кодировка была изменена с фиксированной длиной кодировка UCS-2 к кодировке переменной длины UTF-16. В этой кодировке, каждая кодовая точка представлена одним char и два chars. В последнем случае два символа называются 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 бит