CODIFICHE E "PLAIN
TEXT" Un primo sguardo al confuso insieme delle
codifiche.
La questione degli encoding è lunga e ha sempre creato grande confusione
nei programmatori, l'obiettivo di questo articolo è chiarire le idee
sulle varie codifiche e come comportarsi di fronte ad ognuna. Ma prima
una piccola introduzione.
La prima cosa da comprendere è che non esiste nulla di simile a ciò che
viene definito plain text (puro testo), qualsiasi file di testo è in
realtà una semplice sequenza di byte, e in quanto tale ha bisogno di una
codifica per essere interpretata. Dunque sfatiamo il mito di "plain
text", esso non è né UTF-8, né Latin-1 e neppure ASCII in quanto anche
l'alfabeto inglese potrebbe essere codificato in maniera differente da
come fa ASCII (si pensi ad EBCDIC). Quindi sia ben chiaro che ogni volta
che si apre un file bisogna specificare la codifica che esso utilizza.
CODIFICHE A 7-8 BIT
I sistemi di codifica più semplici: ASCII, ISO e ANSI (codepage
di Windows).
La codifica più conosciuta è probabilmente ASCII (acronimo per American
Standard Code for Information Interchange), un set in grado di
rappresentare 128 caratteri per byte (ovvero un bit viene ignorato, si
tratta infatti di fatto di una codifica a 7 bit) tra i quali vi sono i
principali segni di punteggiatura, le cifre decimali e le lettere
dell'alfabeto inglese maiuscole e minuscole; nonostante la sua fama
(principalmente dovuta alla sua diffusione come base di altri set di
caratteri e alla sua semplicità) ASCII risulta di per sé scarsamente
utile, in quanto non è in grado di rappresentare alcun carattere
accentato, alfabeti differenti da quello inglese o tantomeno ideogrammi
di lingue orientali. Per questo esistono una serie di altre codifiche
che sfruttando il bit inutilizzato riescono ad rappresentare altre 128
configurazioni oltre a quelle di base del set ASCII. Le più note tra
queste codifiche a byte singolo sono quelle dello standard ISO-8859
(ufficialmente ISO/IEC 8859):
- ISO-8859-1 (Latin-1): diffusissima codifica usata per
rappresentare lingue dell'Europa occidentale;
- ISO-8859-2 (Latin-2): codifica usata per rappresentare lingue
dell'Europa centrale;
- ISO-8859-3 (Latin-3): codifica usata per rappresentare lingue
dell'Europa meridionale;
- ISO-8859-4 (Latin-4): codifica usata per rappresentare lingue
dell'Europa settentrionale (più orientata alle lingue baltiche);
- ISO-8859-5 (Latin/Cyrillic): codifica usata per rappresentare
lingue slave;
- ISO-8859-6 (Latin/Arabic): codifica usata per rappresentare la
lingua araba;
- ISO-8859-7 (Latin/Greek): codifica usata per rappresentare la
lingua greca;
- ISO-8859-8 (Latin/Hebrew): codifica usata per rappresentare la
lingua ebraica;
- ISO-8859-9 (Latin-5): simile a Latin-1 ma maggiormente orientata
alle lingue turche;
- ISO-8859-10 (Latin-6): codifica usata per rappresentare lingue
dell'Europa settentrionale;
- ISO-8859-11 (Latin/Thai): codifica usata per rappresentare la
lingua thai;
- ISO-8859-12 (Latin/Devanagari): codifica usata per rappresentare
la lingua Devangagari;
- ISO-8859-13 (Latin-7): codifica usata per rappresentare lingue
baltiche;
- ISO-8859-14 (Latin-8): codifica usata per rappresentare lingue
celtiche;
- ISO-8859-15 (Latin-9): simile a Latin-1 ma include il simbolo
dell'Euro e alcune altre varianti;
- ISO-8859-16 (Latin-10): codifica usata per rappresentare lingue
dell'Europa sud-orientale;
Tutti questi set di caratteri occupano solamente un byte e risultano
particolarmente utili per salvare, memorizzare o trasmettere dati che
utilizzano i caratteri di un solo gruppo delle culture suddette. Le
codifiche in circolazione sono poi ovviamente molte di più, ma oltre a
quelle dello standard ISO vogliamo qui ricordare un tipo di codifiche con
il quale ci si viene a scontrare molto spesso nell'ambito dello
sviluppo: le codifiche di Windows (dette anche code page). Ecco la
lista di quelle disponibili:
- codepage 874: lingua thai;
- codepage 1250: latino dell'Europa orientale;
- codepage 1251: cirillico;
- codepage 1252: latino dell'Europa occidentale (noto anche come
ANSI);
- codepage 1253: greco;
- codepage 1254: turco;
- codepage 1255: ebraico;
- codepage 1256: arabo;
- codepage 1257: baltico;
- codepage 1258: vietnamita;
Queste codifiche sono basate su una bozza che ANSI (l'American National Standards Institute) aveva proposto ma non sono mai state
standardizzate, e per questo le codifiche ISO sono sempre da preferirsi.
Un problema frequente con queste codifiche ANSI è proprio il rischio di
confonderle con le corrispondenti versioni ISO, in primis Latin-1 e il
Windows-1252. Sebbene la codifica Windows-1252 sia un superset di
Latin-1 (ovvero sia con essa del tutto compatibile) è bene non fare
confusione e comunque usare sempre la versione ISO, possibilmente
Latin-9, in quanto include anche il simbolo dell'Euro. Si badi però che Latin-9 non è
invece compatibile con Windows-1252, ad esempio il Latin-9 il simbolo
dell'euro corrisponde alla posizione 164 (A4 in esadecimale), mentre per
Windows-1252 è in 128 (80 in esadecimale). CODIFICHE MULTY-BYTE
Lo standard Unicode.
Le codifiche a byte singolo sono molto compatte ma anche molto limitate,
permettono infatti un numero piuttosto limitato di caratteri (al massimo
256), fatto che genera problemi non solamente nel caso in cui si debba
usare testo in lingue differenti, ma anche in una singola. In questo
articolo ci occuperemo delle codifiche multi-byte definite dallo
standard Unicode, che ha raggiunto l'obiettivo di riunire in un
unico standard tutti i caratteri esistenti. Esso comprende 1'114'112
caratteri (da U+0 a U+10FFFF) suddivisi in 17 "piani" da 65'536
caratteri l'uno, il primo piano (piano 0) è detto Basic Multilingual
Plane (abbreviato BMP) e contiene tutti caratteri necessari
per rappresentare le lingue moderne, gli altri contengono caratteri
supplementari o sono riservati per utilizzi futuri.
Unicode definisce due tipi di codifiche, a lunghezza fissa e a lunghezza
variabile: quelle a lunghezza fissa assicurano ogni carattere occuperà
una certa quantità di byte (con alcune piccole eccezioni per caratteri
combinati), mentre in quelle a lunghezza variabile la lunghezza di un
singolo carattere può variare.
- UCS-2 (2-byte Universal Character Set): codifica con
lunghezza fissa di due byte per carattere in grado di rappresentare
solamente i caratteri del BMP, ovvero il range da U+0 a U+FFFF;
- UTF-16 (16-bit Unicode Transformation Format): codifica
che in sostanza estende UCS-2, sfruttando alcuni valori inutilizzati
per permettere caratteri "surrogati", ovvero caratteri che invece di
occupare due byte ne occupano 4 (per questo UTF-16 rientra nelle
codifiche a lunghezza variabile); in questa maniera è possibile
rappresentare tutti i 17 piani del set Unicode;
- UCS-4 (4-byte Universal Character Set) o UTF-32
(32-bit Unicode Transformation Format): codifica che richiede 4 byte
per ogni carattere, essa è ovviamente a lunghezza fissa in quanto lo
spazio disponibile per un carattere è addirittura sovrabbondante
rispetto a quello richiesto per rappresentare l'intero set Unicode;
il vantaggio di questa codifica è che essendo a lunghezza fissa
minimizza il numero di computazioni necessarie per interpretare il
carattere e al contempo è in grado di rappresentare l'intero set
Unicode;
- UTF-8 (8-bit Unicode Transformation Format): codifica a
lunghezza variabile in cui ogni carattere può occupare da 1 a 4 byte
in grado di coprire l'intero set Unicode; tra quelle trattate finora
è l'unica compatibile con il set ASCII, infatti i caratteri del set
ASCII in UTF-8 vengono rappresentati nella stessa maniera; poiché
ASCII richiede solamente 7-bit, il bit che avanza viene in sostanza
usato per indicare se il carattere continua nel prossimo byte oppure
no; con meccanismi simili UTF-8 può estendersi fino a 4 byte,
comprendo l'intero set Unicode; per le lingue occidentali sono in
genere sufficienti due byte, ma per coprire il BMP sono richiesti 3
byte, gli altri sono riservati per i piani meno comuni;
A questo sorge spontanea la domanda: quale usare? Innanzitutto va
detto che le codifiche Unicode sono da preferirsi a quelle viste in
precedenza, e in secondo luogo la risposta è che dipende. Usare UCS-2
è del tutto sconsigliabile in quanto esiste UTF-16 che è con esso
compatibile ma può l'intero set Unicode. UTF-32 (o UCS-4)
è usato di rado, poiché, sebbene minimizzi l'uso del processore
nell'elaborazione, richiede l'impiego di 4 byte anche per rappresentare
il BMP o addirittura i caratteri del set ASCII (mentre in UTF-8 bastano
da 1 a 3 e in UTF-16 sono sufficienti 2).
In genere UTF-16 viene utilizzato per le stringhe di testo in
memoria, in quanto è un buon compromesso tra spazio occupato ed
efficienza, ma quando lo spazio occupato diventa fondamentale è
preferibile UTF-8, quindi tipicamente nella trasmissione di testo
attraverso la rete o quando deve essere memorizzato su disco. WEB,
HTML, XML E BOM
Le codifiche nel mondo del web e nei formanti documentali
principali.
Se ci si sta chiedendo quali siano le codifiche più diffuse sul web la
risposta è che c'è veramente di tutto, spesso in gran confusione.
Tuttavia alcune codifiche godono di particolare privilegi, in
particolare ISO-8859-1 (Latin-1), UTF-8, UTF-16 e
purtroppo Windows-1252. Latin-1 è, secondo le specifiche,
la codifica di default per i dati che hanno MIME type che comincia per
"text/" trasmessi tramite HTTP. UTF-8 e UTF-16 sono invece
un requisito obbligatorio per tutti i parser XML e in
particolare, in caso la codifica non sia specificata è da intendersi
come UTF-8. Infine Windows-1252 (ANSI) è la codifica di default
in molti sistemi operativi Windows ed è per questo molto diffusa in
editor HTML e di conseguenza sul web.
Come abbiamo detto all'inizio, non esiste un formato "puro testo", ogni
volta che si riceve del testo bisogna conoscerne la codifica, ad esempio
il protocollo HTTP permette di specificarla tramite l'header
Content-Type, o in altri casi formati come HTML e XML permettono di
specificare la codifica direttamente all'interno dei dati. Esistono poi
i BOM (Byte Order Mark), ovvero una sequenza di byte che
viene posta all'inizio di un file o comunque di un flusso di dati per
fornire alcune indicazioni sulla codifica. Il BOM serve per determinare
quale codifica è stata usata e se è Big Endian o Little Endian
(ovvero se il byte più significativo sta all'inizio o alla fine, questo
ha senso solamente nelle codifiche multi-byte). UTF-8 è identificato
dalla sequenza esadecimale EFBBFB, UTF-16 Big Endian da FEFF, UTF-16
Little Endian da FFFE, UTF-32 BE da 0000FEFF e infine UTF-32 LE da
FFFE0000. Il BOM diviene spesso un semplice indicatore che si sta usando
Unicode, soprattutto per UTF-8 che in realtà non soffre di problemi di
endianess. È opinione di molti che usare il BOM non sia una buona
pratica in quanto la codifica utilizzata dovrebbe essere comunicata
tramite altri mezzi (ad esempio l'header HTTP citato poco fa).
|