Finalmente trovo il tempo per mettere on-line qualche appunto relativo al sempre verde tema della codifica dei caratteri.
Sono nozioni di base che tutti dovrebbero conoscere per evitare di brancolare nel buio quando si parla di stringhe e testi gestiti dalle applicazioni.

La codifica dei caratteri (encoding) riguarda la scelta della “lingua” che due o più applicazioni decidono di parlare per scambiarsi delle informazioni.
Se creo la stringa “pippo” nel mio codice, ho solo scritto “pippo” niente di più.
In base alla mia applicazione, es. una servlet, mando la stringa in GET o POST a un’altra applicazione e nell’effettuare l’invio devo decidere con che codifica mandare la stringa ovvero in che lingua parlare con l’altra applicazione.
La stringa arriva all’altra applicazione, che sa con quale codifica interpretare l’input, e solo così può decodificare correttamente il testo e stampare a video i dati  che sono stati spediti.

Spesso si commette l’errore di ignorare il tema dell’encoding e di affidarsi al “default” che può però non essere coerente tra i vari componenti interessati: l’applicazione sorgente, il server su cui l’applicazione risiede, il server di destinazione, l’applicazioni di destinazione e volendo anche il database.
Ovviamente se tutti questi default non sono coordinati tra loro, succederà che visualizzeremo al posto di “pippo” qualcosa di incomprensibile contenente “caratteri strani” quali lettere accentate, punti e virgola e chissà cos’altro.
Volendo fare un esempio di altra natura, viene da se che se aspettate una lettera dalla Francia ragionevolmente leggerete e risponderete scrivendo in francese e se dovete riferire di quella lettera ad un tedesco scriverete poi nella sua lingua, a meno di non esservi tutti e 3 coordinati prima e aver deciso di utilizzare l’inglese come lingua comune.
Una stringa risulta priva di significato se non conoscete la codifica da utilizzare per leggerla.

ACSII e ISO

In origine c’era il codice ASCII, una codifica a 7 bit con i caratteri base che tipicamente coprono la lingua inglese.
Dato che però restava un bit libero si è pensato che l’ottavo bit potesse essere usato per scopi specifici quindi passiamo a ISO8859, una codifica a 8 bit dove l’ottavo bit consente di gestire alfabeti diversi a seconda della codifica specifica che si utilizza. Ne esistono 15 e ISO8859-1 rappresenta l’alfabeto Latino usato per l’italiano e noto anche come Latin1.
L’uso di questo ottavo bit in maniera arbitraria al variare della codifica complica ovviamente la questione e non consente di avere una rappresentazione univoca per un determinato carattere.

UNICODE

Con lo standard di codifica UNICODE si cerca di ovviare al problema.
Unicode infatti assegna un numero univoco ad ogni carattere usato per la scrittura in maniera indipendente da tutto il resto e incorpora, nella primissima parte, i caratteri presenti nella codifica ISO8859-1.
Un carattere Unicode viene rappresentato con la notazione

U+4_CIFRE_ESADECIMALI

Es. La lettera H in Unicode è U+0048 e viene memorizzato usando 2 byte dato che 1 cifra esadecimale può essere rappresentata da 4 bit, 2 alla quarta fa appunto 16.

Questi due byte possono essere codificati come 0048 (big endian) o 4800 (little endian).
Big-endian (byte più significativo a sinistra) e little-endian (byte meno significativo a sinistra) sono due metodi di memorizzazione dei dati che hanno origine dal differente modo, usato dai calcolatori, per immagazzinare in memoria i dati di dimensione superiore al byte. Nel caso dei più comuni processori Intel il formato di memorizzazione è il little-endian.
Lasciando da parte questa caratteristica “legata all’hardware”, l’ordine big-endian è stato scelto come ordine standard per molti dei protocolli più comuni.
A tal proposito, nel caso della codifica Unicode, si parla di Unicode byte order mark. Questo particolare valore numerico, “FE FF”, può essere presente all’inizio di una stringa Unicode e specifica che la nostra stringa va interpretata con la notazione little-endian, quindi invertendo l’ordine delle varie coppie di byte.

UTF-8 e company

Il “problema” di Unicode è però quello di allocare sempre e comunque almeno 2 byte per qualunque tipo di carattere, anche quelli per i quali basterebbero 7 bit. La codifica UTF-8 viene introdotta per avere maggiore flessibilità.
UTF-8 è infatti una codifica dei caratteri Unicode in sequenze di lunghezza variabile di byte.
UTF-8 usa da 1 a 4 byte per rappresentare un carattere Unicode a seconda “dell’intervallo unicode” di appartenenza del carattere stesso.
Questa classe di appartenenza si ricava in base al range numerico in cui ricade il particolare carattere, quindi un carattere base ASCII per cui bastano 7 bit ricadrà nel primo intervallo e UTF-8 lo codificherà con un solo byte.
Esistono infine altri formati di decodifica quali UCS-2, UTF-16 e UTF-32, che partendo da Unicode identificano rispettivamente il carattere con 2 byte (e qui vale ancora little o big endian), 16 bit o 32 bit.

URL Encoding


A contorno di quanto detto foni ad ora, la questione si complica ulteriormente quando facciamo una chiamata http in GET ad un’applicazione.
In una URL, o più in generale un URI, esistono dei caratteri riservati che se usati vanno necessariamente codificati usando l’encoding con la notazione

%+codice_esadecimale

I caratteri riservati sono in tutto 18:

! * ‘ ( ) ; : @ & = + $ , / ? # [ ]

Occorre però effettuare l’encoding anche di tutti gli altri caratteri diversi da lettere e numeri ascii, punto ‘.’, trattino ‘-‘, tilde ‘~’ e underscore ‘_’.
Qualunque altro carattere viene trasformato in UTF-8 e poi codificato con l’url encoding. Ad esempio i segni di maggiore e minore devono essere trasformati se presenti in una url http.

Spero di aver fatto un pò di chiarezza sull’argomento senza commettere dei clamorosi errori.

Riferimenti:

http://www.unicode.org/charts/
http://it.wikipedia.org/wiki/ASCII
http://it.wikipedia.org/wiki/ISO_8859
http://en.wikipedia.org/wiki/ISO/IEC_8859-1
http://it.wikipedia.org/wiki/UTF-8
http://en.wikipedia.org/wiki/Percent-encoding
http://www.w3schools.com/tags/ref_urlencode.asp
http://www.joelonsoftware.com/articles/Unicode.html