Estaba leyendo la documentación para StringBuffer
, en particular, el método reverse () . Esa documentación menciona algo sobre pares sustitutos . ¿Qué es un par sustituto en este contexto? ¿Y qué son los sustitutos bajos y altos ?
java
unicode
utf-16
surrogate-pairs
Raymond
fuente
fuente
String
estar compuesto, no solo de unidades de caracteres. Lástima que Java no te permita usar OO para arreglar eso, pero tanto laString
clase como lasStringBuffer
clases han sidofinal
modificadas. ¿No es un eufemismo por matar? :)Respuestas:
El término "par sustituto" se refiere a un medio de codificación de caracteres Unicode con puntos de código altos en el esquema de codificación UTF-16.
En la codificación de caracteres Unicode, los caracteres se asignan a valores entre 0x0 y 0x10FFFF.
Internamente, Java utiliza el esquema de codificación UTF-16 para almacenar cadenas de texto Unicode. En UTF-16, se utilizan unidades de código de 16 bits (dos bytes). Dado que 16 bits solo pueden contener el rango de caracteres de 0x0 a 0xFFFF, se utiliza cierta complejidad adicional para almacenar valores por encima de este rango (0x10000 a 0x10FFFF). Esto se hace usando pares de unidades de código conocidas como sustitutos.
Las unidades de código sustituto se encuentran en dos rangos conocidos como "sustitutos altos" y "sustitutos bajos", dependiendo de si están permitidos al comienzo o al final de la secuencia de unidades de dos códigos.
fuente
Las primeras versiones de Java representaban caracteres Unicode utilizando el tipo de datos char de 16 bits. Este diseño tenía sentido en ese momento, porque todos los caracteres Unicode tenían valores inferiores a 65.535 (0xFFFF) y podían representarse en 16 bits. Más tarde, sin embargo, Unicode aumentó el valor máximo a 1,114,111 (0x10FFFF). Como los valores de 16 bits eran demasiado pequeños para representar todos los caracteres Unicode en la versión 3.1 de Unicode, se adoptaron valores de 32 bits, llamados puntos de código, para el esquema de codificación UTF-32. Pero los valores de 16 bits son preferibles a los valores de 32 bits para un uso eficiente de la memoria, por lo que Unicode introdujo un nuevo diseño para permitir el uso continuo de los valores de 16 bits. Este diseño, adoptado en el esquema de codificación UTF-16, asigna 1.024 valores a sustitutos altos de 16 bits (en el rango U + D800 a U + DBFF) y otros 1.024 valores a sustitutos bajos de 16 bits (en el rango U + DC00 a U + DFFF).
fuente
Lo que dice la documentación es que las cadenas UTF-16 no válidas pueden volverse válidas después de llamar al
reverse
método, ya que pueden ser las reversas de las cadenas válidas. Un par sustituto (discutido aquí ) es un par de valores de 16 bits en UTF-16 que codifican un único punto de código Unicode; los sustitutos bajos y altos son las dos mitades de esa codificación.fuente
Agregar más información a las respuestas anteriores de esta publicación.
Probado en Java-12, debería funcionar en todas las versiones de Java anteriores a 5.
Como se menciona aquí: https://stackoverflow.com/a/47505451/2987755 ,
cualquier carácter (cuyo Unicode esté por encima de U + FFFF) se representa como un par sustituto, que Java almacena como un par de valores de caracteres, es decir, el Unicode único El carácter se representa como dos caracteres Java adyacentes.
Como podemos ver en el siguiente ejemplo.
1. Longitud:
2. Igualdad:
represente "🌉" en String usando Unicode
\ud83c\udf09
como se muestra a continuación y verifique la igualdad.Java no es compatible con UTF-32
3. Puede convertir caracteres Unicode en cadenas Java
4. String.substring () no considera caracteres suplementarios
Para resolver esto podemos usar
String.offsetByCodePoints(int index, int codePointOffset)
5. Iteración cadena Unicode con BreakIterator
6. Clasificación Cuerdas con Unicode java.text.Collator
7. Carácter de
toUpperCase()
,toLowerCase()
, los métodos no deben utilizarse, en cambio, en mayúsculas y minúsculas uso de cuerdas de especial configuración regional.8.
Character.isLetter(char ch)
no admite, mejor utilizadoCharacter.isLetter(int codePoint)
, para cadamethodName(char ch)
método en la clase de caracteres habrá un tipo de losmethodName(int codePoint)
cuales pueden manejar caracteres suplementarios.9. Especificar charset en
String.getBytes()
, la conversión de Bytes a String,InputStreamReader
,OutputStreamWriter
Ref:
https://coolsymbol.com/emojis/emoji-for-copy-and-paste.html#objects
https://www.online-toolz.com/tools/text-unicode-entities-convertor.php
https: //www.ibm.com/developerworks/library/j-unicode/index.html
https://www.oracle.com/technetwork/articles/javaee/supplementary-142654.html
Más información sobre el ejemplo image1 image2
Otros términos que vale la pena explorar: Normalización , BiDi
fuente
Los pares sustitutos se refieren a la forma en que UTF-16 codifica ciertos caracteres, consulte http://en.wikipedia.org/wiki/UTF-16/UCS-2#Code_points_U.2B10000..U.2B10FFFF
fuente
Pequeño prefacio
Antes de la Versión 3.1, la mayoría de las veces en uso era una codificación de 8 bits, conocida como UTF-8, y una codificación de 16 bits, conocida como UCS-2 o "Juego de caracteres universal codificado en 2 octetos". UTF-8 codifica puntos Unicode como una secuencia de bloques de 1 byte, mientras que UCS-2 siempre toma 2 bytes:
A = 41 - un bloque de 8 bits con UTF-8
A = 0041 - un bloque de 16 bits con UCS-2
Ω = CE A9 - dos bloques de 8 bits con UTF-8
Ω = 03A9 - un bloque de 16 bits con UCS-2
Problema
El consorcio pensó que 16 bits serían suficientes para cubrir cualquier lenguaje legible por humanos, lo que da 2 ^ 16 = 65536 posibles valores de código. Esto fue cierto para el Plano 0, también conocido como BPM o Plano Multilingüe Básico, que incluye 55,445 de 65536 puntos de código en la actualidad. BPM cubre casi todos los idiomas humanos del mundo, incluidos los símbolos chino-japonés-coreano (CJK).
El tiempo pasó y se agregaron nuevos conjuntos de caracteres asiáticos, los símbolos chinos tomaron más de 70,000 puntos solo. Ahora, incluso hay puntos Emoji como parte del estándar 😺. Se agregaron 16 nuevos aviones "adicionales" . La sala UCS-2 no fue suficiente para cubrir algo más grande que el Plano-0.
Decisión Unicode
Crear UTF-16 basado en UCS-2. Haga que UTF-16 sea dinámico, por lo que toma 2 bytes o 4 bytes por punto. Asigne 1024 puntos U + D800 – U + DBFF, llamados High Surrogates, a UTF-16; asigne 1024 símbolos U + DC00 – U + DFFF, llamados sustitutos bajos, a UTF-16.
Con esos cambios, BPM está cubierto con 1 bloque de 16 bits en UTF-16, mientras que todos los "caracteres suplementarios" están cubiertos con pares sustitutos que presentan 2 bloques de 16 bits cada uno, totalmente 1024x1024 = 1 048 576 puntos.
Un sustituto alto precede a un sustituto bajo . Cualquier desviación de esta regla se considera una codificación incorrecta. Por ejemplo, un sustituto sin un par es incorrecto, un sustituto bajo de pie antes de un sustituto alto es incorrecto.
𝄞, 'SÍMBOLO MUSICAL G CLEF', está codificado en UTF-16 como un par de sustitutos 0xD834 0xDD1E (2 por 2 bytes),
en UTF-8 como 0xF0 0x9D 0x84 0x9E (4 por 1 byte),
en UTF-32 como 0x0001D11E (1 por 4 bytes).
Situación actual
Para admitir aplicaciones heredadas con codificaciones UTF-8 / UTF-16 incorrectas , se creó un nuevo estándar WTF-8 , Wobbly Transformation Format. Es compatible con puntos sustitutos arbitrarios, como un sustituto no emparejado o una secuencia incorrecta. Hoy, algunos productos no cumplen con el estándar y tratan a UTF-8 como WTF-8.
Muchos detalles históricos fueron suprimidos para seguir el tema ⚖.
El último estándar Unicode se puede encontrar en http://www.unicode.org/versions/latest
fuente
Un par sustituto son dos 'unidades de código' en UTF-16 que conforman un 'punto de código'. La documentación de Java indica que estos 'puntos de código' seguirán siendo válidos, con sus 'unidades de código' ordenadas correctamente, después del reverso. Además, establece que dos unidades de código sustituto no emparejadas pueden invertirse y formar un par sustituto válido. Lo que significa que si hay unidades de código no emparejadas, ¡entonces existe la posibilidad de que el reverso del reverso no sea el mismo!
Tenga en cuenta, sin embargo, que la documentación no dice nada sobre Graphemes, que son múltiples puntos de código combinados. Lo que significa que e y el acento que lo acompaña todavía se puede cambiar, colocando así el acento antes de la e. Lo que significa que si hay otra vocal antes de la e, puede obtener el acento que estaba en la e.
¡Ay!
fuente