La encoding ISO-8859-1 y la conservación de datos binarios

Leí en un comentario una respuesta de @Esailija a una pregunta mía que

ISO-8859-1 es la única encoding que retiene completamente los datos binarios originales, con coincidencias exactas de byte puntos de código

También leí en esta respuesta por @AaronDigulla que:

En Java, ISO-8859-1 (también conocido como ISO-Latin1) es un mapeo 1: 1

Necesito algo de información sobre esto. Esto fallará (como se ilustra aquí ):

// \u00F6 is ö System.out.println(Arrays.toString("\u00F6".getBytes("utf-8"))); // prints [-61, -74] System.out.println(Arrays.toString("\u00F6".getBytes("ISO-8859-1"))); // prints [-10] 

Preguntas

  1. Admito que no entiendo muy bien, ¿por qué no obtiene los bytes en el código de arriba ?
  2. Lo que es más importante, ¿ dónde se especifica esto ( byte preservar el comportamiento de ISO-8859-1 )? Enlaces a la fuente, o JSL sería bueno. ¿Es la única encoding con esta propiedad?
  3. ¿Está relacionado con que ISO-8859-1 sea ​​el valor predeterminado predeterminado ?

Vea también esta pregunta para ejemplos de contador agradables de otros conjuntos de caracteres.

"\u00F6" no es una matriz de bytes. Es una cadena que contiene un solo char. Ejecute la siguiente prueba en su lugar:

 public static void main(String[] args) throws Exception { byte[] b = new byte[] {(byte) 0x00, (byte) 0xf6}; String s = new String(b, "ISO-8859-1"); // decoding byte[] b2 = s.getBytes("ISO-8859-1"); // encoding System.out.println("Are the bytes equal : " + Arrays.equals(b, b2)); // true } 

Para verificar que esto sea cierto para cualquier byte, simplemente mejore el código de un bucle a través de todos los bytes:

 public static void main(String[] args) throws Exception { byte[] b = new byte[256]; for (int i = 0; i < b.length; i++) { b[i] = (byte) i; } String s = new String(b, "ISO-8859-1"); byte[] b2 = s.getBytes("ISO-8859-1"); System.out.println("Are the bytes equal : " + Arrays.equals(b, b2)); } 

ISO-8859-1 es una encoding estándar. Entonces el lenguaje utilizado (Java, C # o lo que sea) no importa.

Aquí hay una referencia de Wikipedia que afirma que cada byte está cubierto:

En 1992, la IANA registró el mapa de caracteres ISO_8859-1: 1987, más conocido por su nombre MIME preferido de ISO-8859-1 (tenga en cuenta el guión adicional sobre ISO 8859-1), un superconjunto de ISO 8859-1, para usar en Internet. Este mapa asigna los caracteres de control C0 y C1 a los valores de código no asignados, por lo que proporciona 256 caracteres a través de cada valor de 8 bits posible.

(énfasis mío)

Para que una encoding retenga datos binarios originales, necesita asignar cada secuencia de bytes única a una secuencia de caracteres única.

Esto descarta todas las codificaciones multibyte (UTF-8/16/32, Shift-Jis, Big5, etc.) porque no todas las secuencias de bytes son válidas en ellas y, por lo tanto, se decodifican con algún carácter de reemplazo (generalmente? O ). No hay forma de saber a partir de la cadena qué causó el carácter de reemplazo una vez decodificado.

Otra opción es ignorar los bytes no válidos, pero esto también significa que infinitas secuencias de bytes diferentes decodifican a la misma cadena. Puede reemplazar bytes no válidos con su encoding hexadecimal en la cadena como "0xFF" . No hay forma de saber si los bytes originales se decodificaron legítimamente a "0xFF" por lo que tampoco funciona.

Esto deja codificaciones de 8 bits, donde cada secuencia es solo un byte. El byte único es válido si hay un mapeo para él. Pero muchas codificaciones de 8 bits tienen agujeros y no codifican 256 caracteres diferentes.

Para conservar los datos binarios originales, necesita una encoding de 8 bits que codifique 256 caracteres diferentes. ISO-8859-1 no es único en esto. Pero en lo que sí es único, es que el valor del punto de código decodificado también es el valor del byte desde el que se decodificó.

Entonces tienes la cadena decodificada y los bytes codificados, entonces siempre está

 (byte)str.charAt(i) == bytes[i] 

para datos binarios arbitrarios donde str es una new String(bytes, "ISO-8859-1") y bytes es un byte[] .


Tampoco tiene nada que ver con Java. No tengo idea de lo que significa su comentario, estas son propiedades de codificaciones de caracteres, no de lenguajes de progtwigción.