Si je convertis un caractère en byte
puis en char
, ce personnage disparaît mystérieusement et devient autre chose. Comment est-ce possible?
C'est le code:
char a = 'È'; // line 1
byte b = (byte)a; // line 2
char c = (char)b; // line 3
System.out.println((char)c + " " + (int)c);
Jusqu'à la ligne 2, tout va bien:
À la ligne 1, je pourrais imprimer "a" dans la console et indiquer "È".
À la ligne 2, je pouvais imprimer "b" dans la console et indiquerait -56, c’est-à-dire 200 parce que les octets sont signés. Et 200 est "È". Donc c'est encore bien.
Mais qu'est-ce qui ne va pas à la ligne 3? "c" devient autre chose et le programme imprime ? 65480
. C'est quelque chose de complètement différent.
Que dois-je écrire à la ligne 3 pour obtenir le résultat correct?
Un caractère dans Java est une unité de code Unicode traitée comme un nombre non signé. Ainsi, si vous exécutez c = (char)b
_, la valeur obtenue est 2 ^ 16 - 56 ou 65536 - 56.
Ou plus précisément, l'octet est d'abord converti en un entier signé avec la valeur 0xFFFFFFC8
À l'aide de l'extension de signe lors d'une conversion avec élargissement. Ceci est ensuite réduit à 0xFFC8
Lors de la conversion en char
, ce qui se traduit par le nombre positif 65480
.
A partir de la spécification de langue:
5.1.4. Élargissement et réduction de la conversion des primitives
Tout d'abord, l'octet est converti en un entier via une conversion de primitive d'élargissement (§5.1.2), puis l'entier résultant est converti en un caractère en réduisant la conversion de primitive (§5.1.3).
Pour obtenir le bon point, utilisez char c = (char) (b & 0xFF)
qui convertit d'abord la valeur d'octet de b
en entier positif 200
À l'aide d'un masque, en remettant à zéro les 24 premiers bits après conversion: 0xFFFFFFC8
Devient 0x000000C8
Ou le nombre positif 200
En décimales.
Vous trouverez ci-dessus une explication directe de ce qui se passe lors de la conversion entre les types primitifs byte
, int
et char
.
Si vous voulez encoder/décoder des caractères à partir d’octets, utilisez Charset
, CharsetEncoder
, CharsetDecoder
ou l’une des méthodes simples comme new String(byte[] bytes, Charset charset)
ou String#toBytes(Charset charset)
. Vous pouvez obtenir le jeu de caractères (tel que UTF-8 ou Windows-1252) à partir de StandardCharsets
.
new String(byteArray, Charset.defaultCharset())
Cela convertira un tableau d'octets en jeu de caractères par défaut en Java. Il peut générer des exceptions en fonction de ce que vous fournissez avec byteArray.