example - ¿Por qué el String.getBytes() de Java usa "ISO-8859-1"
iso-8859-1 to utf-8 python (4)
de java.lang.StringCoding:
String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;
Esto es lo que se usa desde Java.lang.getBytes (), en linux jdk 7 Siempre tuve la impresión de que UTF-8 es el conjunto de caracteres predeterminado?
Gracias
Es un poco complicado ...
Java intenta utilizar la codificación de caracteres predeterminada para devolver bytes utilizando String.getBytes ().
- El conjunto de caracteres predeterminado lo proporciona la propiedad file.encoding del sistema.
- Esto se almacena en caché y no sirve de nada cambiarlo a través de System.setProperty (..) después de que se inicie la JVM.
- Si la propiedad file.encoding no se asigna a un conjunto de caracteres conocido, entonces se especifica el UTF-8.
.... Aquí está la parte difícil (que probablemente nunca entrará en juego) ...
Si el sistema no puede decodificar o codificar cadenas usando el conjunto de caracteres predeterminado (UTF-8 u otro), entonces habrá un retroceso a ISO-8859-1. Si el respaldo no funciona ... ¡el sistema fallará!
.... Realmente ... (¡jadeo!) ... ¿Podría fallar si mi juego de caracteres especificado no se puede usar, y UTF-8 o ISO-8859-1 también son inutilizables?
Sí. El estado de los comentarios de la fuente Java en el método StringCoding.encode (...):
// Si no podemos encontrar ISO-8859-1 (una codificación requerida), entonces las cosas están muy mal con la instalación.
... y luego llama a System.exit (1)
Entonces, ¿por qué hay un respaldo intencional a ISO-8859-1 en el método getBytes ()?
Es posible, aunque no es probable, que la JVM de los usuarios no admita la decodificación y codificación en UTF-8 o el conjunto de caracteres especificado en el inicio de JVM.
Entonces, ¿se usa correctamente el conjunto de caracteres predeterminado en la clase String durante getBytes ()?
No. Sin embargo, la mejor pregunta es ...
¿String.getBytes () cumple lo que promete?
El contrato tal como se define en el Javadoc es correcto.
El comportamiento de este método cuando esta cadena no puede codificarse en el conjunto de caracteres predeterminado no está especificado. La clase
CharsetEncoder
debe usar cuando se requiere más control sobre el proceso de codificación.
La buena noticia (y mejor manera de hacer las cosas).
Siempre se recomienda especificar explícitamente "ISO-8859-1" o "US-ASCII" o "UTF-8" o el conjunto de caracteres que desee al convertir bytes en cadenas de viceversa, a menos que haya obtenido previamente El conjunto de caracteres predeterminado y asegurado al 100% es el que necesitas.
Utilice este método en su lugar:
public byte[] getBytes(String charsetName)
Para encontrar el valor predeterminado para su sistema, simplemente use:
Charset.defaultCharset()
Espero que ayude.
El método String.getBytes()
parámetros no utiliza ISO-8859-1 de forma predeterminada. Utilizará la codificación de la plataforma predeterminada, si eso se puede determinar. Sin embargo, si falta o es una codificación no reconocida, recae en ISO-8859-1 como "predeterminado por defecto".
Rara vez debería ver esto en la práctica. Normalmente, la codificación predeterminada de la plataforma se detectará correctamente.
Sin embargo, le sugiero que especifique una codificación de caracteres explícita cada vez que realice una operación de codificación o decodificación. Incluso si desea el valor predeterminado de la plataforma, especifíquelo explícitamente.
Elaborar la respuesta de Skeet (que por supuesto es la correcta)
En la fuente de java.lang.String , getBytes()
llama a StringCoding.encode(char[] ca, int off, int len)
que tiene en su primera línea:
String csn = Charset.defaultCharset().name();
Luego (no inmediatamente, sino absolutamente) llama al static byte[] StringEncoder.encode(String charsetName, char[] ca, int off, int len)
donde proviene la línea que citó, pasando como charsetName el csn, así que en esta línea charsetName
será el conjunto de caracteres predeterminado, si existe.
Eso es por razones de compatibilidad.
Históricamente, todos los métodos Java en Windows y Unix que no especificaban un conjunto de caracteres utilizaban el método común en ese momento, es decir, "ISO-8859-1"
.
Como lo mencionaron Isaac y el javadoc, se usa la codificación de la plataforma predeterminada (ver Charset.java ):
594 public static Charset defaultCharset() {
595 if (defaultCharset == null) {
596 synchronized (Charset.class) {
597 String csn = AccessController.doPrivileged(
598 new GetPropertyAction("file.encoding"));
599 Charset cs = lookup(csn);
600 if (cs != null)
601 defaultCharset = cs;
602 else
603 defaultCharset = forName("UTF-8");
604 }
605 }
606 return defaultCharset;
607 }
Siempre especifique el conjunto de caracteres cuando haga una cadena a bytes o bytes a una conversión de cadena.
Incluso cuando, como es el caso de String.getBytes()
, todavía se encuentra un método no en desuso que no toma el juego de caracteres (la mayoría de ellos estaban en desuso cuando apareció Java 1.1). Al igual que con el endianness, el formato de la plataforma es irrelevante, lo que es relevante es la norma del formato de almacenamiento.