UTF-8
UTF-8 (Unicode Transformation F, 8 bit) è una codifica dei caratteri Unicode in sequenze di lunghezza variabile di byte, creata da Rob Pike e Ken Thompson. UTF-8 usa gruppi di byte per rappresentare i caratteri Unicode, ed è particolarmente utile per il trasferimento tramite sistemi di posta elettronica a 8-bit.
UTF-8 usa da 1 a 4 byte per rappresentare un carattere Unicode. Per esempio un solo byte è necessario per rappresentare i 128 caratteri dell'alfabeto ASCII, corrispondenti alle posizioni Unicode da U+0000 a U+007F.
Anche se può sembrare inefficiente rappresentare i simboli Unicode con 4 byte, UTF-8 permette ai sistemi legacy di trasmettere questo super-insieme dello standard ASCII. In più la compressione dei dati è ancora possibile indipendentemente dall'uso di UTF-8.
La IETF (Internet Engineering Task Force) richiede che tutti i protocolli Internet identifichino la codifica dei caratteri utilizzata, e che siano in grado di utilizzare almeno UTF-8.
Descrizione
UTF-8 viene descritto nello standard RFC 3629 (UTF-8, un formato di trasformazione dell'ISO 10646).
Brevemente, i bit che compongono un carattere Unicode vengono suddivisi in gruppi, che vengono poi ripartiti tra i bit meno significativi all'interno dei byte che formano la codifica UTF-8 del carattere.
I caratteri inferiori a 128dec vengono rappresentati con un singolo byte contenente il loro valore; essi corrispondono esattamente ai 128 caratteri ASCII.
In tutti gli altri casi sono necessari fino a 4 byte, ognuno di questi con il bit più significativo impostato a 1, in modo da distinguerli dalla rappresentazione dei caratteri inferiori a 128dec.
Intervallo Unicode esadecimale |
UTF-16 | UTF-8 binario |
Note |
000000 - 00007F | 00000000 0xxxxxxx | 0xxxxxxx | Caratteri equivalenti al codice ASCII; I byte iniziano con 0 |
000080 - 0007FF | 00000xxx xxxxxxxx | 110xxxxx 10xxxxxx | il primo byte inizia per 110 o 1110, il successivo(i) con 10 |
000800 - 00FFFF | xxxxxxxx xxxxxxxx | 1110xxxx 10xxxxxx 10xxxxxx | |
010000 - 10FFFF | 110110xx xxxxxxxx 110111xx xxxxxxxx |
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | UTF-16 richiede l'uso di coppie surrogate; viene sottratto il valore esadecimale 0x10000, in modo che la sequenza dei bit non coincida con quella usata da UTF-8 |
Per esempio, il carattere alef (א), corrispondente all'Unicode 0x05D0, viene rappresentato in UTF-8 con questo procedimento:
- ricade nell'intervallo da 0x0080 a 0x07FF. Secondo la tabella verrà rappresentato con due byte. 110xxxxx 10xxxxxx.
- l'esadecimale 0x05D0 equivale al binario 101-1101-0000.
- gli undici bit vengono copiati in ordine nelle posizioni marcate con x. 110-10111 10-010000.
- il risultato finale è la coppia di byte 11010111 10010000, o in esadecimale 0xD7 0x90
Riassumendo, i primi 128 caratteri vengono rappresentati con un singolo byte. I successivi 1920 ne richiedono due, e comprendono gli alfabeti Latino con diacritici, Greco, Cirillico, Copto, Armeno, Ebraico e Arabo. I restanti caratteri UCS-2 hanno bisogno di tre byte, tutto il resto di quattro.
In realtà UTF-8 è in grado di usare sequenze fino a 6 byte, coprendo l'intervallo da 0x00 a 0x7FFFFFFF (31 bit), ma nel 2003 UTF-8 è stato limitato dallo standard RFC 3629 per coprire solo l'intervallo descritto formalmente nello standard Unicode, ovvero da 0x00 a 0x10FFFF. In precedenza i soli byte che non potevano comparire in una sequenza UTF-8 valida erano 0xFE e 0xFF. Con l'introduzione del precedente limite, il numero di byte non usati dalla codifica UTF-8 è salito a 13: 0xC0, 0xC1, e da 0xF5 a 0xFF. Anche se la nuova definizione di UTF-8 limita in modo consistente l'insieme di caratteri Unicode rappresentabili, il problema delle rappresentazioni multiple dello stesso carattere, un potenziale rischio per la sicurezza, scompare in quanto ognuna di queste sequenze conterrebbe uno dei byte non usati, risultando non valida.
UTF-8 Modificato
Il Linguaggio di programmazione Java usa per la codifica dei caratteri una variazione non standard di UTF-8, conosciuta tra gli utenti di Java come UTF-8 Modificato.
Ci sono due differenze tra la codifica UTF-8 standard e quella modificata. La prima differenza è che il carattere nullo (0x0000) viene rappresentato con due byte anzichè uno, nello specifico come 11000000 10000000 (0xC0 0x80). In questo modo ci si assicura che nessuna stringa di caratteri contenga il carattere null (0x00), probabilmente per prevenire problemi di troncamento delle stringhe in linguaggi come il C, che lo usano per indicare la fine di una stringa.
La seconda differenza riguarda la rappresentazione dei caratteri al di fuori del BMP (Basic Multilingual Plane). Utilizzanto l'UTF-8 standard questi caratteri vengono rappresentati con 4 byte, secondo il formato nella tabella precedente. Con UTF-8 modificato questi caratteri vengono prima rappresentati come coppie surrogate (come in UTF-16), successivamente entrambi i caratteri della coppia vengono codificati individualmente in UTF-8. Il motivo di questa differenza non è ovvio. In Java un carattere è lungo 16 bit, quindi alcuni caratteri Unicode devono essere rappresentati come sequenze di due caratteri. Questo aspetto del linguaggio è precedente all'introduzione dei piani supplementari in Unicode, ma è importante sia per fattori legati alle prestazioni, che per la compatibilità all'indietro, ed è quindi improbabile che venga corretto. L'encoding modificato assicura che che una stringa codificata possa essere decodificata un carattere (a 16 bit) per volta, anzichè un carattere Unicode per volta. Sfortunatamente questo vuol dire che i caratteri che richiedono 4 byte per essere rappresentati in UTF-8, siano rappresentati in UTF-8 modificato con sequenze di 6 byte.
Motivazioni di UTF-8
In conseguenza dei meccanismi di funzionamento di UTF-8, le sequenze di byte godono di queste proprietà:
- Il bit pù significativo di ogni sequenza composta di un singolo byte è sempre 0.
- I bit più significativi del primo di una sequenza di più byte indicano la lunghezza della sequenza. Questi bit sono 110 per le sequenze di due byte, e 1110 per quelle di tre.
- I byte successivi al primo in una sequenza composta da più byte hanno sempre 10 come bit più significativi
UTF-8 è stato progettato per soddisfare queste tre proprietà, in modo da garantire che nessuna sequenza di byte corrispondente a uno specifico carattere sia contenuta in una sequenza più lunga, usata per codificare un carattere diverso. Grazie a questa caratteristica la ricerca di parole o frasi all'interno di un testo può essere effettuata tramite confronto byte per byte; qualche precedente sistema di codifica basato su sequenze di lunghezza variabile di byte (per esempio Shift-JIS) non godeva di questa proprietà, rendendo gli algoritmi di confronto tra stringhe complicati. Nonostante si possa obiettare che questa caratteristica aggiunga ridondanza alla codifica del testo, i vantaggi sono maggiori degli svantaggi; inoltre la compressione dei dati non è uno degli scopi di Unicode, e va considerata separatamente. Infine, ancora grazie a questa proprietà, se uno o più byte andassero persi per errori di trasmissione o per corruzione dei dati, sarebbe possibile risincronizzare la decodifica all'inizio del carattere successivo, limitando i danni.