Perché UTF-8 spreca diversi bit nella sua codifica

13

Secondo l' articolo di Wikipedia , UTF-8 ha questo formato:

First code Last code Bytes Byte 1    Byte 2    Byte 3    Byte 4
point      point     Used
U+0000     U+007F    1     0xxxxxxx
U+0080     U+07FF    2     110xxxxx  10xxxxxx
U+0800     U+FFFF    3     1110xxxx  10xxxxxx  10xxxxxx
U+10000    U+1FFFFF  4     11110xxx  10xxxxxx  10xxxxxx  10xxxxxx
x means that this bit is used to select the code point.

Questo spreca due bit su ogni byte di continuazione e un bit nel primo byte. Perché UTF-8 non è codificato come segue?

First code Last code Bytes Byte 1    Byte 2    Byte 3
point      point     Used
U+0000     U+007F    1     0xxxxxxx
U+0080     U+3FFF    2     10xxxxxx  xxxxxxxx
U+0800     U+1FFFFF  3     110xxxxx  xxxxxxxx  xxxxxxxx

Salverebbe un byte quando il punto di codice è fuori dal piano di base multilingue o se il punto di codice è nell'intervallo [U + 800, U + 3FFF].

Perché UTF-8 non è codificato in modo più efficiente?

    
posta qbt937 09.11.2014 - 20:50
fonte

5 risposte

24

Questo è fatto in modo da poter rilevare quando ci si trova nel mezzo di una sequenza multi-byte. Quando guardi i dati UTF-8, sai che se vedi 10xxxxxx , sei nel bel mezzo di un carattere multibyte e dovresti eseguire il backup nello stream finché non vedi 0xxxxxx o 11xxxxxx . Usando il tuo schema, i byte 2 o 3 potrebbero facilmente finire con pattern come 0xxxxxxx o 11xxxxxx

Tieni anche presente che la quantità di dati salvati varia interamente sul tipo di dati di stringa che stai codificando. Per la maggior parte dei testi, anche quelli asiatici, raramente si vedranno mai quattro byte di caratteri con testo normale. Inoltre, le stime ingenue della gente su come apparirà il testo sono spesso sbagliate. Ho un testo localizzato per UTF-8 che include stringhe giapponesi, cinesi e coreane, ma in realtà è il russo che occupa più spazio. (Poiché le nostre stringhe asiatiche hanno spesso caratteri latini intervallati per nomi propri, punteggiatura e simili e perché la parola cinese media è di 1-3 caratteri mentre la parola russa media è molti, molti altri.)

    
risposta data 09.11.2014 - 20:56
fonte
5

Il modo ufficiale consente al decodificatore di sapere quando si trova nel mezzo della tupla e sa saltare i byte (o andare indietro) finché il byte inizia con 0 o 11 ; ciò impedisce i valori garbage quando un singolo byte viene corrotto.

    
risposta data 09.11.2014 - 20:55
fonte
2

Risposta breve, la proposta non distingue tra il primo byte e i byte di continuazione.

Il modello di bit all'estremità superiore del primo byte indica con quanti byte viene creato il carattere effettivo. Questi pattern forniscono anche un riconoscimento degli errori durante l'analisi di una stringa. Se stai leggendo il primo byte (apparentemente) di un personaggio e ottieni 10xxxxxx, allora sai che sei fuori sincrono.

    
risposta data 09.11.2014 - 21:25
fonte
2

Ciò che non è stato menzionato è che se hai una sequenza corretta di punti di codice e un puntatore che è garantito per puntare al primo byte di un punto di codice, con UTF-8 puoi facilmente trovare il puntatore a il primo byte del punto di codice precedente (salta tutti i byte che iniziano con 01xx xxxx). Con la tua codifica, è impossibile senza esaminare potenzialmente tutti i byte fino all'inizio della stringa.

Considera le sequenze di (2n + 2) byte

0xxxxxxx
n times (10xxxxxx, 10xxxxxx)
0xxxxxxx

e

n times (10xxxxxx, 10xxxxxx)
(10xxxxxx, 0xxxxxxx)

Se hai un puntatore al primo byte del primo punto di codice dopo questa sequenza, devi esaminare tutti byte per scoprire se l'ultimo punto di codice è 0xxxxxxx o (10xxxxxx, 0xxxxxxx).

Esistono schemi di codifica più efficienti, in cui è possibile eseguire il punto di codice precedente in tempo costante e correggere i puntatori nel mezzo di un punto di codice. Consenti i seguenti codici:

X where X < 128
YX where 128 ≤ Y < 236, X < 128
ZYY where 236 ≤ Z < 256, 0 ≤ Y < 236. 

Se uno dei tre byte precedenti è ≥ 236, allora è l'inizio di una sequenza di 3 byte, perché non ci possono essere due di questi byte all'interno di una sequenza di 3 byte valida. Altrimenti, se uno dei due byte precedenti è ≥ 128, allora è l'inizio di una sequenza di due byte. Altrimenti, il byte precedente è un singolo byte < 128.

La ricerca di una sottostringa diventa leggermente più difficile. Si consiglia di escludere zero byte in modo che una stringa contenga solo un byte zero se contiene un punto di codice zero.

    
risposta data 02.04.2017 - 00:38
fonte
-2

Risposta breve, la tua proposta utf-8 è impossibile da sincronizzare. Una volta che avrai una sequenza corrotta nel flusso di byte, non puoi mai sincronizzare realmente alla successiva sequenza valida o singlebyte. Questo perché in effetti hai un byte iniziale, a partire da 10 o 110, ma i seguenti byte possono essere anche startbytes e anche singlebytes.

Il modo in cui utf-8 è stato progettato, è sempre possibile rilevare un singolo byte, un startbyte e un byte successivo.

    
risposta data 28.04.2015 - 12:59
fonte

Leggi altre domande sui tag