Come funziona la "codifica a larghezza variabile" UTF-8?


110

Lo standard Unicode ha un numero sufficiente di punti di codice da richiedere 4 byte per memorizzarli tutti. Questo è ciò che fa la codifica UTF-32. Eppure la codifica UTF-8 in qualche modo li comprime in spazi molto più piccoli usando qualcosa chiamato "codifica a larghezza variabile".

In effetti, riesce a rappresentare i primi 127 caratteri di US-ASCII in un solo byte che assomiglia esattamente al vero ASCII, quindi puoi interpretare un sacco di testo ASCII come se fosse UTF-8 senza farci nulla. Trucco pulito. Quindi, come funziona?

Chiederò e risponderò alla mia domanda qui perché ho appena letto un po 'per capirlo e ho pensato che potrebbe far risparmiare tempo a qualcun altro. In più forse qualcuno può correggermi se ho sbagliato qualcosa.


8
Straight Unicode non richiede 32 bit per codificare tutti i suoi punti di codice. Una volta rivendicavano quel numero di punti di codice possibili, ma dopo che UTF-8 decollò, si limitarono intenzionalmente a 21 bit, in modo che UTF-8 non supererà mai i 4 byte per carattere. Unicode attualmente richiede solo 17 bit per contenere tutti i possibili punti di codice. Senza questa limitazione, UTF-8 avrebbe potuto arrivare a 6 byte per carattere.
Warren Young,

@ Warren: per lo più accurato, ma Unicode è un codice a 21 bit (da U + 0000 a U + 10FFFF).
Jonathan Leffler

2
@ Warren: UTF-8 limitato a 4 byte avrebbe potuto supportare fino a U + 1FFFFF. La restrizione a U + 10FFFF è stata fatta per il bene di UTF-16.
dan04

@ dan04 Abbiamo qualche semplice spiegazione di come sia limitato a U + 10FFFF da UTF-16? Sarebbe bello saperne di più su questo.
A letubby

@ A-letubby: poiché i codici UTF-16 "surrogati" sono allocati in modo tale che ci siano 1024 surrogati principali e 1024 surrogati trail (e possono essere usati solo in coppia), per creare 2 ^ 20 (circa un milione) caratteri aggiuntivi disponibile oltre il BMP. Aggiunto ai 2 ^ 16 caratteri disponibili nel BMP, questo rende 0x110000 caratteri possibili.
dan04

Risposte:


129

Ogni byte inizia con alcuni bit che indicano se si tratta di un punto di codice a byte singolo, un punto di codice multibyte o una continuazione di un punto di codice multibyte. Come questo:

0xxx xxxx    A single-byte US-ASCII code (from the first 127 characters)

I punti di codice multibyte iniziano ciascuno con alcuni bit che essenzialmente dicono "ehi, devi anche leggere il byte successivo (o due o tre) per capire cosa sono". Loro sono:

110x xxxx    One more byte follows
1110 xxxx    Two more bytes follow
1111 0xxx    Three more bytes follow

Infine, i byte che seguono quei codici di avvio hanno tutti questo aspetto:

10xx xxxx    A continuation of one of the multi-byte characters

Poiché puoi dire che tipo di byte stai guardando dai primi bit, anche se qualcosa viene alterato da qualche parte, non perdi l'intera sequenza.


14
C'è di più nella storia di questo - perché la codifica deve essere la codifica più breve possibile per il carattere, il che finisce per significare che i byte 0xC0 e 0xC1 non possono apparire in UTF-8, per esempio; e, infatti, nessuno dei due può 0xF5..0xFF. Consulta le FAQ UTF-8 su unicode.org/faq/utf_bom.html o unicode.org/versions/Unicode5.2.0/ch03.pdf
Jonathan Leffler

2
Perché non poteva usare un solo carattere per dire next char is continuation? Se ottenessimo un carattere di 3 byte, sarebbe come:, 1xxxxxxx 1xxxxxxx 0xxxxxxxquindi verrebbe sprecato meno spazio.

9
@ Soaku rende UTF-8 un cosiddetto codice "auto-sincronizzante". Ciò significa che se a causa di errori mancano parti della sequenza, è possibile rilevarlo e scartare tutto ciò che è stato confuso. Se leggi un byte che inizia con 10xx e non c'è un byte "start" precedente, puoi scartarlo perché non ha senso. Se avessi un sistema come quello descritto e uno dei primi byte è andato perso, potresti ritrovarti con un carattere diverso e valido senza alcuna indicazione di alcun tipo di errore. Inoltre faciliterà l'individuazione del successivo carattere valido e correggerà i byte di "continuazione" mancanti.
htmlcoderexe

9

RFC3629 - UTF-8, un formato di trasformazione di ISO 10646 è l'autorità finale qui e ha tutte le spiegazioni.

In breve, diversi bit in ogni byte della sequenza da 1 a 4 byte codificata UTF-8 che rappresenta un singolo carattere vengono utilizzati per indicare se si tratta di un byte finale, un byte iniziale e, in tal caso, quanti byte seguono. I bit rimanenti contengono il carico utile.


1
Ummmm, sciocco io, pensavo che lo standard Unicode fosse l'autorità finale su UTF-8
John Machin

6
Lo standard Unicode definisce lo stesso Unicode. Non definisce vari metodi, attuali e futuri, che possono essere utilizzati per codificare testi Unicode per una varietà di scopi (come l'archiviazione e il trasporto). UTF-8 è uno di quei metodi e il riferimento sopra è al documento che lo definisce.
azheglov

1
RFC3629, pagina 3, sezione 3. dice "UTF-8 è definito dallo standard Unicode".
John Machin

La ricerca di collegamenti su unicode.org mi ha portato alla sezione 3.9 dello standard Unicode e in particolare alla definizione D92 (e anche tangenzialmente D86). Non ho idea in che misura questo collegamento sarà utile quando vengono rilasciate nuove versioni, ma immagino che vogliano mantenere stabili gli identificatori di sezione e definizione tra le versioni.
tripleee

4

UTF-8 era un altro sistema per memorizzare la tua stringa di punti di codice Unicode, quei numeri magici U +, in memoria usando byte a 8 bit. In UTF-8, ogni punto di codice da 0 a 127 viene memorizzato in un singolo byte. Solo i punti di codice 128 e superiori vengono memorizzati utilizzando 2, 3, infatti, fino a 6 byte.

Estratto dal minimo assoluto che ogni sviluppatore di software deve assolutamente sapere su Unicode e set di caratteri (nessuna scusa!)


Questo è un buon articolo, ma sembra che Joel abbia torto riguardo alla lunghezza massima della sequenza; la pagina di Wikipedia mostra solo 1..4 byte per carattere.
rilassarsi il

4
Come ho detto sopra, quando UTF-8 è stato creato per la prima volta, Unicode rivendicava fino a 32 bit per i punti di codice, non perché ne avessero davvero bisogno, solo perché 32 bit è un valore conveniente e avevano già superato il limite precedente di caratteri a 16 bit. Dopo che UTF-8 si è dimostrato popolare, hanno scelto di limitare per sempre il numero massimo di punti di codice a 2 ^ 21, che è il valore più grande che è possibile codificare con 4 byte dello schema UTF-8. Ci sono ancora meno di 2 ^ 17 caratteri in Unicode, quindi possiamo più che quadruplicare il numero di caratteri in Unicode con questo nuovo schema.
Warren Young,

Ok ma non la spiegazione richiesta da OP.
Nishant,

2
Questo non risponde alla domanda.
Koray Tugay
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.