2010-12-15 25 views
33

Estoy realmente confundido con respecto a la codificación de cadenas en Java. Tengo un par de preguntas. Por favor, ayúdenme si conoce la respuesta:¿Cuál es la codificación de caracteres de String en Java?

1) ¿Cuál es la codificación nativa de las cadenas de Java en la memoria? Cuando escribo String a = "Hello", ¿en qué formato se almacenará? Como Java es independiente de la máquina, no creo que el sistema haga la codificación.

2) Leí en la red que "UTF-16" es la codificación predeterminada, pero me confundí porque cuando escribo ese int a = 'c' obtengo el número del carácter en la tabla ASCII. Entonces, ¿son ASCII y UTF-16 lo mismo?

3) Tampoco estaba seguro de qué depende el almacenamiento de una cadena en la memoria: sistema operativo, idioma?

+0

Debería considerar dividirlas en preguntas individuales, ya que son realmente muy diferentes. # 2 probablemente pueda ser respondida aquí: http://stackoverflow.com/questions/1490218/utf-16-to-ascii-conversion-in-java –

Respuesta

15

1) Las cadenas son objetos, que normalmente contienen una matriz char y la longitud de las cadenas. La matriz de caracteres generalmente se implementa como una matriz contigua de palabras de 16 bits, cada una con un carácter Unicode en orden de bytes nativo.

2) Asignar un valor de carácter a un entero convierte el código de carácter Unicode de 16 bits en su equivalente entero. Por lo tanto, 'c', que es U + 0063, se convierte en 0x0063, o 99.

3) Como cada String es un objeto, contiene otra información que los miembros de su clase (por ejemplo, palabra de descripción de clase, palabra de bloqueo/semáforo, etc.).

Adendum
El objeto contenidos dependen de la implementación JVM (que determina la sobrecarga inherente asociado con cada objeto), y cómo la clase es en realidad codificada (es decir, algunas bibliotecas pueden ser más eficientes que otros).

Ejemplo
Una implementación típica asignará una sobrecarga de dos palabras por instancia de objeto (para el descriptor de la clase/puntero, y una palabra de control de semáforos/bloqueo); un objeto String también contiene una longitud de int y una referencia de matriz char[]. El contenido de los caracteres reales de la cadena se almacena en un segundo objeto, la matriz char[], que a su vez tiene asignadas dos palabras, más una longitud de matriz, más tantos elementos de char de 16 bits como sea necesario para la cadena (más cualquier carácter adicional que quedaron colgando cuando se creó la cuerda).

adición 2
El caso que uno carbón representa el carácter de uno Unicode sólo es cierto en la mayoría de los casos. Esto implicaría la codificación UCS-2 y verdadera antes de 2005. Pero ahora Unicode se ha hecho más grande y las cadenas deben codificarse usando UTF-16, donde un único carácter Unicode puede usar doschar s en Java String.

Eche un vistazo al código fuente real para la implementación de Apache, p. at:
http://www.docjar.com/html/api/java/lang/String.java.html

+0

En realidad, ¿qué piensas decir en tu 3) parte? Contiene otra información, ¿así que ...? –

+0

"La asignación de un valor de carácter a un número entero convierte el código de carácter Unicode de 16 bits en su equivalente entero". Lo que es un poco confuso aquí es que la codificación Unicode coincide con ASCII para los primeros 256 caracteres. Unicode se correlaciona con ASCII extendido (8 bits) para los primeros 256 caracteres; ASCII extendido, a su vez, corresponde directamente con ASCII de 7 bits para los primeros 128. Por lo tanto, 'c' se codifica como 0x63 en Unicode, ASCII extendido y ASCII. Es por esto que verías el int para 'c' y pensarás que es ASCII (que sortof es :). –

+0

@HawkeyeParker: Sí, el ASCII de 7 bits (ISO 646) y el ISO 8859-1 de 8 bits (Latin-1) son subconjuntos propios de Unicode. Dicho esto, Java codifica todos los valores de caracteres como Unicode de 16 bits. –

29
  1. Java almacena cadenas como UTF-16 internamente.

  2. "codificación predeterminada" no es del todo correcto. Java almacena cadenas como UTF-16 internamente, pero la codificación utilizada externamente, la "codificación predeterminada del sistema", varía de una plataforma a otra e incluso puede modificarse mediante variables de entorno en algunas plataformas.

    ASCII es un subconjunto de Latin 1 que es un subconjunto de Unicode. UTF-16 es una forma de codificar Unicode. Por lo tanto, si realiza su prueba int i = 'x' para cualquier carácter que se encuentre en el rango ASCII, obtendrá el valor ASCII. Sin embargo, UTF-16 puede representar muchos más caracteres que ASCII.

  3. Desde el java.lang.Character docs:

    La plataforma Java 2 utiliza la representación UTF-16 en arrays de char y en las clases String y StringBuffer.

    Por lo tanto, se define como parte de la plataforma Java 2 que UTF-16 se utiliza para estas clases.

+0

El uso de las matrices char y char solo está definido para la API pública y externa para String y StringBuffer. El almacenamiento interno de los personajes es específico de la implementación. – jarnbjo

+0

@jarnbjo Lo anterior es una cita directa de los documentos. El tipo de datos 'char' en Java representa una unidad de código UTF-16 (no un carácter, también conocido como punto de código Unicode), así que creo que es bastante seguro decir que la representación del texto en Java es UTF-16. Sí, posiblemente una implementación podría elegir hacer algo diferente bajo las coberturas, pero al final tendrían que hacer que se vea como si estuvieran usando UTF-16. –

+0

Dado que no hay forma de acceder al almacenamiento interno de las clases String y StringBuffer, tiene sentido suponer que la instrucción que cita se aplica a ella. – jarnbjo

2

Si bien esto no responde a su pregunta, merece la pena señalar que ... En el código de bytes de Java (archivo de clase), la cadena se almacena en UTF-8. http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html

+1

OP preguntó sobre el almacenamiento en memoria, no el formato de archivo '.class'. –

+1

@Loadmaster Creo que es una información útil, y explícitamente mencioné que es el archivo de clase, ¿cuál es su probelma? – Ralph

+1

Pero no responde la pregunta. Podría publicarlo como un comentario y comenzar con algo como "Aunque esto no responde a su pregunta, vale la pena señalar que ..." Sin embargo, esta es una información útil, no tenía idea de que usaran UTF- 8. ¿Cuál es el punto de? Significa que JVM tiene que convertir cada cadena a UTF-16 al inicio. –

1

Editar: gracias al jefe de carga por ayudarme a corregir mi respuesta :)

1) Todo el procesamiento de cuerda interna se hace en UTF-16.

2) ASCII es un subconjunto de UTF-16.

3) Internamente en Java es UTF-16. Por lo demás, depende de dónde estés, sí.

+2

Las cadenas se almacenan internamente (en memoria) como 'char []', cada elemento contiene un carácter Unicode UTF-16 de 16 bits. UTF-8 no se usa para almacenar cadenas internamente, sino que se usa para convertir flujos de E/S a/desde cadenas. –

+0

@LoadMaster: ¿ha cambiado con el tiempo? Java siempre estuvo internamente en UTF-16? – LaGrandMere

+0

Sí, 'String' siempre ha usado un' char [] 'interno para almacenar sus valores de caracteres. –

Cuestiones relacionadas