2010-03-28 39 views
31

Una Java char es 2 bytes (tamaño máximo de 65.536) pero hay 95,221 caracteres Unicode. ¿Esto significa que no puede manejar ciertos caracteres Unicode en una aplicación Java?Codificación de Java Unicode

¿Esto se reduce a la codificación de caracteres que está utilizando?

Respuesta

32

Puede manejarlos todos si tiene la precaución suficiente.

Java char es un UTF-16 code unit. Para los caracteres con punto de código> 0xFFFF, se codificará con 2 char s (un par suplente).

Consulte http://www.oracle.com/us/technologies/java/supplementary-142654.html para saber cómo manejar esos caracteres en Java.

(Por cierto, en Unicode 5.2 existen 107,154 caracteres asignados de 1,114,112 ranuras.)

+1

La página vinculada anterior es una de las más claras que he leído en la diferenciación entre las diferentes codificaciones, lo que utilizar las API de JVM, el significado de cierta fraseología ("punto de código" frente a "unidad de código") y lo que proporciona el JNI. –

+0

El siguiente sitio es muy claro pero bastante detallado. Incluso va más allá de la definición de puntos de código, y muestra cómo manejar y contar Grafemas (personaje renderizado completo que puede consistir en más de un punto de código, cuando se usan marcas diacríticas combinatorias) http://illegalargumentexception.blogspot.jp/2009/ 05/java-rough-guide-to-character-encoding.html –

+1

Después de la revisión de @ AllenGeorge, estaba emocionado de leer el artículo solo para descubrir que el enlace ahora está roto :(Ruddy Oracle y su incapacidad para 301 correctamente. Cualquiera que pueda actualizar el enlace? – dimo414

1

Desde el OpenJDK7 documentation for String:

Una cadena representa una cadena en el formato UTF-16 en el que suplementaria caracteres están representados por pares suplentes (consulte la sección Representaciones de caracteres Unicode en la clase de caracteres para obtener más información acerca de ). Los valores de índice hacen referencia a unidades de código de char, por lo que un carácter suplementario utiliza dos posiciones en un String .

14

Java usa UTF-16. Un solo Java char solo puede representar caracteres del basic multilingual plane. Otros personajes deben estar representados por un par suplente de dos char s. Esto se refleja en métodos de API como String.codePointAt().

Y sí, esto significa que una gran cantidad de código Java se romperá de una forma u otra cuando se utiliza con caracteres fuera del plano multilingüe básico.

+2

¿Cómo manejan 'String.length',' substring', etc. cadenas con estos caracteres? –

+5

@Bart: length() cuenta caracteres tales como dos caracteres, subcadena() también lo hace y los dividirá felizmente, resulti ng en UTF-16 no válido. Esto se debe a que dichos caracteres se convirtieron en parte de Unicode solo después de que se diseñó Java y Java no realiza cambios de última hora. Por lo tanto, se agregaron nuevos métodos para tratar con pares de sustitución, pero los anteriores no se modificaron. –

+2

+1 para señalar que la mayoría del código de Java está roto. – ceving

3

Eche un vistazo al artículo Unicode 4.0 support in J2SE 1.5 para conocer más acerca de los trucos inventados por Sun para proporcionar soporte para todos los puntos de código Unicode 4.0.

En resumen, se encuentran los siguientes cambios para Unicode 4.0 en Java 1.5:

  • char es una unidad de UTF-16 código, no un punto de código
  • nuevas API de bajo nivel utilizar un int para representar un punto de código Unicode
  • API de alto nivel se han actualizado para comprender pares suplentes
  • una preferencia hacia secuencia Char APIs en lugar de los métodos basados ​​en carbón de leña

Dado que Java no tiene 32 caracteres de bits, voy a dejar de juzgar si podemos llamar a este buen soporte para Unicode.

10

Para añadir a las otras respuestas, algunos puntos para recordar:

  • Un Java char toma siempre 16 bits de.

  • Un de caracteres Unicode, cuando se codifica como UTF-16, toma "casi siempre" (no siempre) de 16 bits: eso es porque hay más de 64 K caracteres Unicode. Por lo tanto, un carácter Java no es un carácter Unicode (aunque "casi siempre" lo es).

  • "Casi siempre", arriba, significa los primeros 64K puntos de código de Unicode, rango 0x0000 a 0xFFFF (BMP), que toman 16 bits en la codificación UTF-16.

  • Un carácter Unicode no BMP ("raro") se representa como dos caracteres Java (representación sustituta). Esto se aplica también a la representación literal como una cadena: For example, the character U+20000 is written as "\uD840\uDC00".

  • Corolarios: string.length() devuelve el número de caracteres de java, no de caracteres Unicode. Una cadena que tiene solo un carácter Unicode "raro" (por ejemplo, U + 20000) devolvería length() = 2. La misma consideración se aplica a cualquier método que trate con secuencias de caracteres.

  • Java tiene poca inteligencia para tratar con caracteres Unicode que no son BMP como un todo. Hay algunos métodos de utilidad que tratan a los personajes como puntos de código, representados por ejemplo: Character.isLetter(int ch). Esos son los métodos reales totalmente Unicode.

+0

¿No te refieres a 0x0000 a 0xFFFF? Solo escribes 3 F's. – JoelFan

+0

@JoelFan Reparado, gracias. – leonbloy

2

Aquí está la documentación de Oracle en Unicode Character Representations. O, si lo prefiere, un more thorough documentation here.

El tipo de datos char (y por lo tanto el valor que un objeto de personaje encapsula) se basan en la especificación Unicode original, que caracteres define como entidades de 16 bits de ancho fijo. El estándar Unicode ha sido cambiado desde entonces para permitir caracteres cuya representación en requiera más de 16 bits. El rango del código legal puntos ahora es U + 0000 a U + 10FFFF, conocido como valor escalar Unicode. (Refiérase a la definición de la U + n notación en la norma Unicode.)

El conjunto de caracteres de U + 0000 a U + FFFF se refiere a veces como el plano multilingüe básico (BMP). Los caracteres cuyos puntos de código son mayores que U + FFFF se denominan 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, caracteres suplementarios se representan como un par de valores char, el primero de el rango de sustitutos altos, (\ uD800- \ uDBFF), el segundo de la gama de sustitutos bajos (\ uDC00- \ uDFFF)

Un valor char, por lo tanto, representa básica Plane multilingüe (BMP) puntos de código, incluyendo los puntos de código de sustitución, o unidades de código de la codificación UTF-16.Un valor int representa todos los puntos de código Unicode, incluyendo puntos de código suplementarios. Los bits inferiores (menos significativos) 21 bits de int se utilizan para representar puntos de código Unicode y los 11 bits superiores de (más significativos) deben ser cero. A menos que se especifique lo contrario, el comportamiento con respecto a los caracteres complementarios y valores CHAR sustitutas es como sigue:

  • Los métodos que sólo aceptan un valor Char no puede apoyar caracteres complementarios. 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 de si está seguido de cualquier valor de bajo sustituto en una cadena sería representa 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).