Что такое «суррогатная пара» в Java? - PullRequest
133 голосов
/ 05 мая 2011

Я читал документацию для StringBuffer, в частности метод reverse () . В этой документации упоминается что-то о суррогатных парах . Что такое суррогатная пара в этом контексте? И что такое низкий и высокий суррогаты?

Ответы [ 6 ]

115 голосов
/ 05 мая 2011

Термин «суррогатная пара» относится к средству кодирования символов Unicode с высокими кодовыми точками в схеме кодирования UTF-16.

В кодировке символов Unicode символы отображаются в значения между 0x0 и0x10FFFF.

Внутренне Java использует схему кодирования UTF-16 для хранения строк текста Unicode.В UTF-16 используются 16-битные (двухбайтовые) кодовые единицы.Поскольку 16 бит могут содержать только диапазон символов от 0x0 до 0xFFFF, некоторая дополнительная сложность используется для хранения значений выше этого диапазона (от 0x10000 до 0x10FFFF).Это делается с использованием пар кодовых единиц, известных как суррогаты.

Суррогатные кодовые единицы находятся в двух диапазонах, известных как «высокие суррогаты» и «низкие суррогаты», в зависимости от того, разрешены ли они в начале или в концепоследовательность из двух кодовых единиц.

43 голосов
/ 27 ноября 2017

Ранние версии Java представляли символы Unicode, используя 16-битный тип данных char. В то время этот дизайн имел смысл, потому что все символы Юникода имели значения меньше 65 535 (0xFFFF) и могли быть представлены в 16 битах. Позже, однако, Unicode увеличил максимальное значение до 1,114,111 (0x10FFFF). Поскольку 16-разрядные значения были слишком малы, чтобы представлять все символы Unicode в версии 3.1 Unicode, 32-разрядные значения, называемые кодовыми точками, были приняты для схемы кодирования UTF-32. Но 16-битные значения предпочтительнее 32-битных для эффективного использования памяти, поэтому Unicode представил новый дизайн, позволяющий продолжить использование 16-битных значений. Эта конструкция, принятая в схеме кодирования UTF-16, присваивает 1024 значения 16-разрядным старшим суррогатам (в диапазоне U + D800 - U + DBFF) и еще 1024 значения 16-разрядным старшим суррогатам (в диапазоне U + DC00 до U + DFFF). Он использует высокий суррогат, за которым следует низкий суррогат - суррогатная пара - для представления (произведение 1024 и 1024) 1,048,576 (0x100000) значений между 65,536 (0x10000) и 1,114,111 (0x10FFFF).

22 голосов
/ 05 мая 2011

В этой документации говорится, что недопустимые строки UTF-16 могут стать действительными после вызова метода reverse, поскольку они могут быть обращены к действительным строкам. Суррогатная пара (обсуждаемая здесь ) - это пара 16-битных значений в UTF-16, которые кодируют одну кодовую точку Unicode; низкие и высокие суррогаты - это две половины этого кодирования.

7 голосов
/ 28 февраля 2019

Добавление дополнительной информации к ответам выше от this post

Протестировано в java-12, должно работать во всех версиях java выше 5.

Как упомянуто здесь: https://stackoverflow.com/a/47505451/2987755,
любой символ (чей Unicode выше U + FFFF) представлен как суррогатная пара, которую Java хранит в виде пары значений char, т.е. один символ Unicode представляется как два соседних символа java.
Как мы можем видеть в следующем примере.
1. Длина:

"?".length()  //2, Expectations was it should return 1

"?".codePointCount(0,"?".length())  //1, To get number of Unicode character in Java String  

2.Равенство:
Представьте «?» в строку, используя Unicode \ud83c\udf09, как показано ниже, и проверьте равенство.

"?".equals("\ud83c\udf09") // true

Java не поддерживает UTF-32

"?".equals("\u1F309") // false  

3.Вы можете преобразовать символ Unicode в строку Java

"?".equals(new String(Character.toChars(0x0001F309))) //true

4.String.substring () не учитывает дополнительные символы

"??".substring(0,1) //"?"
"??".substring(0,2) //"?"
"??".substring(0,4) //"??"

. Для решения этой проблемы мы можем использовать String.offsetByCodePoints(int index, int codePointOffset)

"??".substring(0,"??".offsetByCodePoints(0,1) // "?"
"??".substring(2,"??".offsetByCodePoints(1,2)) // "?"

5.Итерация строки Unicode с BreakIterator
6. Сортировка строк с Unicode java.text.Collator
7. Символы toUppercase, нижний регистр не должны использоваться, вместо этого используйте строчные буквы верхнего регистраи строчные буквы конкретной локали
8. Character.isLetter(char ch) не поддерживает, лучше использовать Character.isLetter(int codePoint), для каждого метода methodName(char ch) в классе Character будет тип methodName(int codePoint), который может обрабатывать дополнительные символы.
9. Укажите кодировку в String.getBytes(), переводя из байтов в строку, InputStreamReader, OutputStreamWriter

Ref:
https://coolsymbol.com/emojis/emoji-for-copy-and-paste.html#objects
https://www.online -toolz.com /tools / text-unicode-entity-convertor.php
https://www.ibm.com/developerworks/library/j-unicode/index.html
https://www.oracle.com/technetwork/articles/javaee/supplementary-142654.html

Подробнее о примере image1 image2
Другие термины, которые стоит изучить: Нормализация , BiDi

6 голосов
/ 05 мая 2011

Суррогатные пары относятся к способу кодирования определенных символов UTF-16, см. http://en.wikipedia.org/wiki/UTF-16/UCS-2#Code_points_U.2B10000..U.2B10FFFF

3 голосов
/ 14 июня 2017

Суррогатная пара - это две «кодовые единицы» в UTF-16, которые составляют одну «кодовую точку».В документации Java говорится, что эти «кодовые точки» все равно будут действительными, а их «кодовые единицы» будут упорядочены правильно после обратного.Далее говорится, что две непарные единицы суррогатного кода могут быть обращены и образовать действительную суррогатную пару.Это означает, что если есть непарные единицы кода, то есть вероятность того, что обратная сторона реверса может быть не одинаковой!,Это означает, что e и акцент, который идет вместе с ним, могут все еще быть переключены, таким образом, помещая акцент перед e.Это означает, что если перед е есть еще один гласный, он может получить ударение, которое было на е.

Yikes!

...