que - ¿Cómo almacena Java los caracteres UTF-16 en su tipo de char de 16 bits?
utf-8 encoding (2)
Básicamente, las cadenas almacenan una secuencia de unidades de código UTF-16 ... que no es lo mismo que almacenar una secuencia de puntos de código Unicode.
Cuando se requiere un personaje fuera del plano multilingüe básico, eso ocupa dos unidades de código UTF-16 dentro de la String
.
La mayoría de las operaciones de String
- length()
, charAt
, substring()
etc. se ocupan de los números de las unidades de código UTF-16. Sin embargo, hay operaciones como codePointAt()
que tratará con puntos de código Unicode completos ... aunque los índices todavía se expresan en términos de unidades de código UTF-16.
EDITAR: si quieres guardar un punto de código que no sea BMP en un solo char
, básicamente no tienes suerte. Es como querer almacenar más de 256 valores distintos en una variable de byte
... simplemente no funciona. Siguiendo las convenciones para representar un punto de código en otro lugar (por ejemplo, en String
), es mejor usar una variable int
.
Según la Especificación Java SE 7 , Java usa el estándar Unicode UTF-16 para representar caracteres. Al imaginar una String
como una simple matriz de variables de 16 bits, cada una con un carácter, la vida es simple.
Desafortunadamente, hay puntos de código para los cuales 16 bits simplemente no son suficientes (creo que era 16/17 de todos los caracteres Unicode). Por lo tanto, en una String
, esto no plantea un problema directo, porque cuando desee almacenar uno de estos ~ 1.048.576 caracteres utilizando dos bytes adicionales , simplemente se usarán dos posiciones de matriz en esa String
.
Esto, sin plantear ningún problema directo , funciona para String
s, porque siempre puede haber dos bytes adicionales. Aunque cuando se trata de variables individuales que, a diferencia de la codificación UTF-16, tienen una longitud fija de 16 bits , ¿cómo pueden almacenarse estos caracteres y, en particular, cómo lo hace Java con su "char" de 2 bytes? tipo ?
La respuesta está en el javadoc :
El tipo de datos char (y, por lo tanto, el valor que encapsula un objeto Character) se basa en la especificación original Unicode, que define caracteres como entidades de 16 bits de ancho fijo. El estándar Unicode ha sido cambiado desde entonces para permitir caracteres cuya representación requiera más de 16 bits.
El rango de puntos de código legal ahora es U + 0000 a U + 10FFFF, conocido como valor escalar Unicode. (Consulte la definición de la notación U + n en el estándar Unicode.) El conjunto de caracteres de U + 0000 a U + FFFF a veces se denomina Plano Bilingüe Básico Básico (BMP). Los caracteres cuyos puntos de código son mayores que U + FFFF se llaman caracteres suplementarios. La plataforma Java 2 usa la representación UTF-16 en matrices char y en las clases String y StringBuffer. En esta representación, los caracteres suplementarios se representan como un par de valores char, el primero del rango de sustitutos altos, (/ uD800- / uDBFF), el segundo del rango de sustitutos bajos (/ uDC00- / uDFFF).
Por lo tanto, un valor de char representa los puntos de código de plano multilingüe básico (BMP), incluidos los puntos de código sustituto o las unidades de código de la codificación UTF-16. Un valor int representa todos los puntos de código Unicode, incluidos los puntos de código suplementarios. Los 21 bits más bajos (menos significativos) de int se utilizan para representar puntos de código Unicode y los 11 bits superiores (más significativos) deben ser cero.
A menos que se especifique lo contrario, el comportamiento con respecto a caracteres suplementarios y valores de caracteres suplentes es el siguiente: Los métodos que solo aceptan un valor de caracteres no pueden admitir caracteres suplementarios. Tratan los valores de char de los rangos de sustitución como caracteres indefinidos. Por ejemplo, Character.isLetter (''/ uD840'') devuelve false, aunque este valor específico si es seguido por cualquier valor de bajo sustituto en una cadena representaría una letra. Los métodos que aceptan un valor int admiten todos los caracteres Unicode, incluidos los caracteres suplementarios. Por ejemplo, Character.isLetter (0x2F81A) devuelve verdadero porque el valor del punto de código representa una letra (un ideograma CJK). En la documentación API de Java SE, el punto de código Unicode se usa para valores de caracteres en el rango entre U + 0000 y U + 10FFFF, y la unidad de código Unicode se usa para valores de caracteres de 16 bits que son unidades de código de la codificación UTF-16. Para obtener más información sobre la terminología Unicode, consulte el Glosario Unicode.
Dicho simplemente :
- los 16 bits para una regla de char se diseñaron para una versión anterior del estándar Unicode
- a veces necesita dos caracteres para representar una runa Unicode (punto de código) que no está en el plano multilingüe básico. Este tipo de "funciona" porque no usa caracteres con frecuencia, especialmente para manejar runas Unicode fuera del BMP.
Incluso más simple dijo:
- un char de java no representa un punto de código Unicode (bueno, no siempre).
Como un aparte, se puede notar que la evolución de Unicode para extender más allá del BMP hizo que el UTF-16 sea irrelevante en todo el mundo, ahora que el UTF-16 ni siquiera habilita una proporción fija de caracteres byte. Es por eso que los idiomas más modernos se basan en UTF-8. Este manifesto ayuda a entenderlo.