Pourquoi le codage US-ASCII accepte-t-il les caractères non US-ASCII?
-
28-10-2019 - |
Question
Considérez le code suivant:
public class ReadingTest {
public void readAndPrint(String usingEncoding) throws Exception {
ByteArrayInputStream bais = new ByteArrayInputStream(new byte[]{(byte) 0xC2, (byte) 0xB5}); // 'micro' sign UTF-8 representation
InputStreamReader isr = new InputStreamReader(bais, usingEncoding);
char[] cbuf = new char[2];
isr.read(cbuf);
System.out.println(cbuf[0]+" "+(int) cbuf[0]);
}
public static void main(String[] argv) throws Exception {
ReadingTest w = new ReadingTest();
w.readAndPrint("UTF-8");
w.readAndPrint("US-ASCII");
}
}
Résultat observé:
µ 181
? 65533
Pourquoi le deuxième appel de readAndPrint()
(celui utilisant US-ASCII) réussit-il?Je m'attendrais à ce qu'il lance une erreur, car l'entrée n'est pas un caractère approprié dans cet encodage.Quelle est la place dans l'API Java ou JLS qui impose ce comportement?
La solution
L'opération par défaut lors de la recherche d'octets non décodables dans le flux d'entrée est de les remplacer par le caractère Unicode U + CARACTÈRE DE REMPLACEMENT FFFD .
Si vous souhaitez modifier cela, vous pouvez transmettre un CharacterDecoder
au InputStreamReader
qui a un autre CodingErrorAction
configuré:
CharsetDecoder decoder = Charset.forName(usingEncoding).newDecoder();
decoder.onMalformedInput(CodingErrorAction.REPORT);
InputStreamReader isr = new InputStreamReader(bais, decoder);
Autres conseils
Je dirais que c'est la même chose que pour le constructeur
String(byte bytes[], int offset, int length, Charset charset)
:
Cette méthode remplace toujours les séquences de caractères malformés et non mappables par la chaîne de remplacement par défaut de ce jeu de caractères.La classe java.nio.charset.CharsetDecoder doit être utilisée lorsque plus de contrôle sur le processus de décodage est nécessaire.
En utilisant CharsetDecoder
, vous pouvez spécifier un CodingErrorAction
différent.