Recientemente me di cuenta de que no entiendo completamente el proceso de codificación de cadenas de Java.De la compilación al tiempo de ejecución, ¿cómo funciona realmente la codificación de Java String?
Considere el siguiente código:
public class Main
{
public static void main(String[] args)
{
System.out.println(java.nio.charset.Charset.defaultCharset().name());
System.out.println("ack char: ^"); /* where^= 0x06, the ack char */
}
}
Dado que los caracteres de control son interpreted differently between windows-1252 and ISO-8859-1, elegí el carbón ack
para la prueba.
Ahora lo compilo con diferentes codificaciones de archivos, UTF-8, windows-1252 y ISO-8859-1. Ambas compilan exactamente lo mismo, byte por byte verificado por md5sum
.
Luego ejecutar el programa:
$ java Main | hexdump -C
00000000 55 54 46 2d 38 0a 61 63 6b 20 63 68 61 72 3a 20 |UTF-8.ack char: |
00000010 06 0a |..|
00000012
$ java -Dfile.encoding=iso-8859-1 Main | hexdump -C
00000000 49 53 4f 2d 38 38 35 39 2d 31 0a 61 63 6b 20 63 |ISO-8859-1.ack c|
00000010 68 61 72 3a 20 06 0a |har: ..|
00000017
$ java -Dfile.encoding=windows-1252 Main | hexdump -C
00000000 77 69 6e 64 6f 77 73 2d 31 32 35 32 0a 61 63 6b |windows-1252.ack|
00000010 20 63 68 61 72 3a 20 06 0a | char: ..|
00000019
correctamente da salida a la 0x06
no importa qué codificación se está utilizando.
Ok, sigue produciendo el mismo 0x06
, que se interpretaría como el carácter imprimible [ACK] por las páginas de códigos de windows-1252.
Eso me lleva a algunas preguntas:
- está siendo compilado espera que la página de códigos/juego de caracteres del archivo de Java para ser idéntico al juego de caracteres por defecto del sistema bajo el cual está siendo compilado? ¿Son los dos siempre sinónimos?
- La representación compilada no parece depender del juego de caracteres en tiempo de compilación, ¿es así?
- ¿Esto implica que las cadenas dentro de los archivos Java se pueden interpretar de manera diferente en el tiempo de ejecución si no utilizan caracteres estándar para el conjunto de caracteres/configuración regional actual?
- ¿Qué más debería saber realmente acerca de la codificación de cadenas y caracteres en Java?
No está claro a qué se refiere con "compilarlo con diferentes codificaciones de archivo". ¿Quiere decir que guarda el archivo en diferentes codificaciones y luego compila cada uno de esos archivos usando el modificador de codificación en javac? Si es así, ¿cómo sabe qué basura aleatoria se está terminando en los archivos fuente después de guardarlos en esas codificaciones? No puede poner un carácter de control literal en su fuente y esperar que sobreviva a la serialización de caracteres codificados. –
Un archivo no es más que una secuencia de bytes. Esos bytes se interpretan de manera diferente dependiendo de la codificación de caracteres en los que se supone que están. Por lo tanto, me refiero a cadenas que contienen 'char's que pueden interpretarse de manera diferente, ya sea en tiempo de ejecución o en tiempo de compilación, asumiendo el archivo fue codificado en diferentes conjuntos de caracteres. –
Para ser explícito sobre el paso de compilación, utilicé la propiedad de codificación sun para establecer el juego de caracteres en tiempo de compilación: 'javac -encoding windows-1252 Main.java', con el conjunto de codificación apropiado. –