La codifica dei caratteri in Java

Questo post è il seguito dell’introduzione alla codifica dei caratteri. Ti consiglio di leggere l’introduzione se non conosci bene l’argomento.

In Java le stringhe sono gestite dalla classe String. Il primo modo per instanziare una stringa è lo “string literal“:
String s = “hello world”;

All’interno della classe String i caratteri sono memorizzati con una versione particolare della codifica UTF-16. Ma questo non è importante per l’utilizzo della classe, dato che i metodi pubblici rielaborano la stringa in base alla codifica che preferiamo. Quando si inizializza una stringa con un literal, il compilatore converte la stringa dalla codifica originale (quella del file sorgente), alla codifica UTF-16, e scrive l’array risultante nel bytecode, che sarà poi caricato in memoria a runtime. Se la codifica del file sorgente non permette la rappresentazione di un determinato carattere, è possibile comunque rappresentarlo con la “Unicode escape”, per esempio “\u0108”.

Esiste un apposito tipo di dato per i caratteri, char, che è composto da due byte (quindi 16 bit), ed è pensato proprio per memorizzare i caratteri nella codifica UTF-16 di Java.

Dato che una stringa è un array di caratteri, e quindi di byte, possiamo anche usare l’apposito costruttore:
String s3 = new String(new byte[] {-61, -96, -61, -88, -61, -84, -61, -78, -61, -71});
(Nota: i numeri negativi sono dati dal fatto che il tipo byte è in complemento a due).

Il costruttore interpreta i valori dell’array secondo la codifica di default configurata sulla jvm. La codifica si può impostare con il parametro
-Dfile.encoding=<codifica>

Nell’esempio i caratteri sono codificati in UTF-8. Quindi, se la codifica della jvm è UTF-8, l’istruzione
System.out.println(s3);
stampa “àèìòù”. Ma, ad esempio, con la codifica ISO-8859-1, l’output è “Ã Ã¨Ã¬Ã²Ã¹”.

Il metodo println ottiene l’array di byte secondo la codifica di default, e la scrive in output. Quindi, successivamente, la stringa dovrà essere riletta utilizzando la stessa codifica, per esempio dal terminale che visualizza l’output del programma o dal file in cui viene scritto.

Per ottenere la stringa nella codifica che vogliamo, si utilizza il metodo “getBytes”. Chiamato senza parametri ritorna l’array di byte secondo la codifica di default. Oppure possiamo passare un oggetto di tipo Charset che rappresenta la codifica desiderata o, infine, direttamente il nome della codifica sotto forma di stringa. E’ quindi possibile instanziare un oggetto String utilizzando una codifica, e poi ottenere la stessa stringa in una codifica diversa.

Spesso gli oggetti che lavorano con le stringhe permettono di specificare la codifica che si vuole utilizzare per elaborare le informazioni, per scriverle in output e per interpretare eventuali array di byte o char in ingresso.