¿Por qué Java’s String.getBytes () usa “ISO-8859-1”?

de java.lang.StringCoding:

String csn = (charsetName == null) ? "ISO-8859-1" : charsetName; 

Esto es lo que se utiliza de Java.lang.getBytes (), en Linux jdk 7 ¿Siempre tuve la impresión de que UTF-8 es el juego de caracteres predeterminado?

Gracias

Es un poco complicado …

Java intenta usar la encoding de caracteres predeterminada para devolver bytes utilizando String.getBytes ().

  • El juego de caracteres predeterminado es proporcionado por la propiedad file fileing.
  • Esto se almacena en caché y no sirve de nada cambiarlo a través de System.setProperty (..) después de que se inicie 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 … (jadeó!) … ¿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 encoding requerida), entonces las cosas están muy mal con la instalación.

… y luego llama a System.exit (1)


Entonces, ¿por qué existe una alternativa intencional a ISO-8859-1 en el método getBytes ()?

Es posible, aunque no probable, que la JVM de los usuarios no admita la deencoding y la encoding en UTF-8 o el juego de caracteres especificado en el inicio de la JVM.

Entonces, ¿el juego de caracteres predeterminado se usa correctamente en la clase String durante getBytes ()?

No. Sin embargo, la mejor pregunta es …


¿String.getBytes () entrega 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 juego de caracteres predeterminado no está especificado. La clase CharsetEncoder debe usar cuando se requiere más control sobre el proceso de encoding.


Las buenas noticias (y una 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 juego de caracteres predeterminado y está 100% seguro de que es el que necesita.

Utilice este método en su lugar:

 public byte[] getBytes(String charsetName) 

Para encontrar el valor predeterminado para su sistema, solo use:

 Charset.defaultCharset() 

Espero que ayude.

El método sin parámetros String.getBytes() no utiliza ISO-8859-1 de forma predeterminada. Utilizará la encoding de plataforma predeterminada, si eso puede determinarse. Sin embargo, si eso falta o es una encoding no reconocida, vuelve a ISO-8859-1 como un “valor predeterminado predeterminado”.

Raramente deberías ver esto en la práctica. Normalmente, la encoding predeterminada de la plataforma se detectará correctamente.

Sin embargo, le sugiero que especifique una encoding de caracteres explícita cada vez que realice una operación de encoding o deencoding. Incluso si desea el valor predeterminado de la plataforma, especifíquelo explícitamente.

Eso es por razones de compatibilidad.

Históricamente, todos los métodos de Java en Windows y Unix que no especificaban un juego de caracteres usaban el común en ese momento, que es "ISO-8859-1" .

Como menciona Isaac y javadoc, se usa la encoding de la plataforma por defecto (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 para convertir cadenas.

Incluso cuando, como es el caso de String.getBytes() , todavía se encuentra un método no obsoleto que no toma el conjunto de caracteres (la mayoría de ellos estaban obsoletos cuando apareció Java 1.1). Al igual que con endianness, el formato de la plataforma es irrelevante, lo relevante es la norma del formato de almacenamiento.

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 el charsetName será el charsetName caracteres predeterminado si existe.