ISO-8859-1 encodage et conservation des données binaires

j'ai lu dans un comment à une réponse de @Esailija à une de mes questions que

ISO-8859-1 est le seul codant pour bien conserver les données binaires d'origine, avec en octets exactementcodepoint correspond à

j'ai aussi lu dans ce réponse par @AaronDigulla que:

en Java, ISO-8859-1 (a. K. un ISO-Latin1) est un mapping 1: 1

j'ai besoin d'un peu de perspicacité là-dessus. Cela échouera (comme illustré ici ):

// 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]

Questions

  1. je reconnais que je ne comprends pas tout à fait - pourquoi ne reçoit-il pas les octets dans le code au-dessus de ?
  2. le plus important, où est ce ( comportement de préservation des bytes ISO-8859-1 ) spécifié - liens vers la source, ou JSL serait agréable. Est-il le seul encodage avec cette propriété ?
  3. est-il lié à ISO-8859-1 étant le défaut par défaut ?

Voir aussi cette question pour compteur belle des exemples provenant d'autres jeux de caractères.

5
demandé sur Community 2013-04-10 16:11:27

2 réponses

"\u00F6" n'est pas un byte array. C'est une chaîne contenant un seul caractère. Exécutez le test suivant à la place:

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
}

pour vérifier que ceci est vrai pour n'importe quel byte, il suffit d'améliorer le code une boucle à travers tous les octets:

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 est un encodage standard. Donc le langage utilisé (Java, C# ou autre) n'a pas d'importance.

voici un référence Wikipédia qui prétend que chaque octet est couvert:

en 1992, L'IANA a enregistré la carte de caractères ISO_8859-1:1987, plus communément connue sous son nom MIME préféré de ISO-8859-1 (notez le trait d'Union supplémentaire par rapport à ISO 8859-1), un super-ensemble de ISO 8859-1, pour une utilisation sur L'Internet. Cette carte assigne les caractères de contrôle C0 et C1 aux valeurs de code non affectées et fournit donc 256 caractères par l'intermédiaire de toutes les valeurs possibles de 8 bits.

(c'est moi qui souligne)

11
répondu JB Nizet 2014-07-25 05:27:16

pour qu'un encodage puisse conserver les données binaires originales, il doit mapper chaque séquence d'octets unique à une séquence de caractères unique.

ceci exclut tous les encodages multi-octets (UTF-8/16/32, Shift-Jis, Big5 etc) parce que toutes les séquences d'octets ne sont pas valides en eux et ainsi serait décoder à un certain caractère de remplacement (généralement ? ou.)� Il n'y a aucun moyen de dire à partir de la corde ce qui a causé le caractère de remplacement après avoir été décodé.

Une autre option est d'ignorer les octets invalides, mais cela signifie aussi que les séquences d'octets décoder à la même chaîne. Vous pouvez remplacer les octets invalides par leur encodage hexadécimal dans la chaîne comme "0xFF" . Il n'y a aucun moyen de dire si les octets originaux ont été décodés au "0xFF" pour que ça ne marche pas non plus.

cela laisse des encodages à 8 bits, où chaque séquence n'est qu'un seul octet. L'octet simple est valide si il y a un mappage. Mais de nombreux Les encodages 8-bits ont des trous et n'encodent pas 256 caractères différents.

pour conserver les données binaires originales, vous avez besoin d'un encodage 8 bits qui Code 256 caractères différents. ISO-8859-1 n'est pas unique dans cette. Mais ce qui est unique, c'est que la valeur du point de code décodé est aussi la valeur du byte il a été décodé.

donc vous avez la chaîne décodée, et les octets encodés, alors il est toujours

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

pour les binaires arbitraires données où str est new String(bytes, "ISO-8859-1") et bytes " est un byte[] .


cela n'a rien à voir avec Java. Je n'ai aucune idée de ce que signifie son commentaire, ce sont des propriétés d'encodage de caractères et non des langages de programmation.

3
répondu Esailija 2013-04-10 23:07:31