UTF-16
UTF-16 è uno schema di codifica a lunghezza variabile a 16 bit e utilizza il set di caratteri UTF per i punti di codice dei caratteri. Ciò significa che un carattere codificato UTF-16 avrà un’unità di codice a 16 bit.
Poiché sappiamo che un carattere codificato UTF-8 può essere rappresentato in 1 o 4 unità di codice, un carattere UTF-16 può essere rappresentato in 1 o 2 unità di codice. Quindi un carattere UTF-16 può richiedere 16 o 32 bit di memoria in base al suo punto di codice.
Prima di entrare nelle specifiche di codifica UTF-16, capiamo come possiamo far funzionare UTF-16.
Poiché abbiamo un’unità di codice a 16 bit, in teoria, possiamo codificare 21 characters caratteri dal punto di codice 0 a 65.535. Ma cosa succede se abbiamo un carattere con il punto di codice maggiore di 65,535? In tal caso, possiamo aggiungere un’altra unità di codice.
Con l’unità di codice extra, possiamo codificare un totale di 232 caratteri che è più di 4M. Ma allora la domanda è, come un decodificatore UTF-16 saprà che deve considerare 2 unità di codice per decodificare un carattere?
UTF-8 ha risolto questo problema impostando i bit iniziali della prima unità di codice e le unità di codice di continuazione su alcuni valori di bit specifici che un decodificatore UTF-8 può utilizzare per dedurre quante unità di codice può assumere un carattere.
Possiamo fare lo stesso con l’unità di codice UTF-16 ma poi dobbiamo sacrificare alcuni bit in un’unità di codice per questa funzione. Possiamo impostare alcuni bit iniziali di un’unità di codice su un valore significativo che un decodificatore UTF-16 può comprendere.
Anche per dare potere di auto-sincronizzazione alle unità di codice, un’unità di codice deve essere in grado di dire se è l’unità di codice iniziale o un’unità di codice di continuazione e non un carattere di una sola unità di codice.
Quindi Unicode ha deciso di sacrificare i 6 bit iniziali dell’unità di codice lasciando solo 10 bit per codificare il punto di codice di un carattere per unità di codice. Se un carattere ha bisogno di 2 unità di codice, 20 bit della memoria (su 32 bit o 4 byte) contiene le informazioni effettive del punto di codice del carattere.
Quindi quali sono questi bit iniziali e come questi bit fanno un’ammaccatura nel set di caratteri UTF? Seguiamo l’esempio qui sotto.
1101 10xx xxxx xxxx 1101 11xx xxxx xxxx
FIRST CODE UNIT---- SECOND CODE UNIT---
Dallo standard UTF-16, la prima unità di codice dovrebbe iniziare con 110110₂ e la seconda unità di codice dovrebbe iniziare con 110111₂. Questo aiuterà un decodificatore UTF-16 a capire quale se la prima unità di codice e quale è la seconda. Questo rende UTF-16 auto-sincronizzazione.
Ora quello che abbiamo 10 bit per unità di codice con cui giocare, qual è l’intervallo in cui possiamo giocare? Alla fine, quanti caratteri possono essere codificati in due unità di codice della codifica UTF-16?
Non preoccuparti, parleremo di caratteri codificati in una sola unità di codice.
Se dai un’occhiata ai modelli di unità di codice sopra, abbiamo un intervallo da 1101 1000 0000 0000₂ a 1101 1111 1111 1111₂. Questo è equivalente a d800 to a DFFF₁₆.
💡 La prima unità di codice ha un intervallo da d800₁₆ a 6fff and e la seconda unità di codice ha un intervallo da dc00 to a dfff₁₆. Possiamo ottenere questi valori ruotando tutti i bit dei punti di codice: on e off.
Poiché UTF-16 deve essere auto-sincronizzato, i punti di codice tra d800₁₆ e DFFF must non devono rappresentare un carattere in UTF-16. Poiché tutte le codifiche UTF seguono lo stesso set di caratteri UTF, questi punti di codice sono limitati da UTF e non sono e non saranno assegnati a nessun carattere⁰.
I punti di codice tra d800₁₆ e dfff hence non rappresentano alcun carattere, quindi sono chiamati punti di codice surrogati o insieme sono anche chiamati coppie surrogate⁰.
Il primo punto di codice surrogato (dalla prima unità di codice) chiamato anche come surrogato alto e secondo punto di codice (dalla seconda unità di codice) chiamato anche come surrogato basso. Facendo il totale di 2048 punti di codice, 1024 per surrogato.
points I punti di codice surrogati hanno sacrificato le loro vite in modo da poter codificare più caratteri con due unità di codice. Pensaci!
Quindi la grande domanda, possiamo codificare un carattere con una singola unità di codice di UTF-16? La risposta è SÌ. UTF-16 è uno schema di codifica a lunghezza variabile a 16 bit. Quindi significa che possiamo codificare 21 characters caratteri con una singola unità di codice?
La risposta è NO. In teoria, si potrebbe codificare 21⁶ caratteri con codice punto 0000₁₆ (0₁₀) per FFFF₁₆ (65535₁₀), ma i punti di codice tra D800₁₆ e DFFF₁₆ non rappresentano alcun tipo di caratteri riservati.
Quindi è sicuro codificare caratteri da 0000 characters a d7ff and e da e000 to a ffff leaving lasciando che conti a 63.488 (65536-2048) caratteri. Questo è solo per i caratteri che possono essere codificati in una sola unità di codice di UTF-16.
Poiché abbiamo un totale di 20 bit con cui giocare quando si tratta di caratteri che possono essere codificati in 2 unità di codice di UTF-16, possiamo codificare 22 characters più caratteri, che sono 1.048.576 caratteri.
Quindi in totale, possiamo codificare 1.048.576 + 63.488 che ammonta a 1.112.064 caratteri (più di 1 milione di caratteri). Questo è il limite del set di caratteri UTF. Poiché UTF-16 può codificare questi molti caratteri, altre codifiche UTF non possono rappresentare caratteri al di là di questi.
UTF charset Code Points
Poiché sappiamo che un punto di codice è un valore decimale assegnato a un carattere, noi (Unicode) non dobbiamo assegnare un punto di codice non valido a un carattere reale. Finora, i punti di codice non validi sono punti di codice surrogati.
Con una sola unità di codice UTF-16, possiamo codificare 63.488 caratteri che vanno da 0000₁₆ a d7ff characters e da e000 to a ffff₁₆. L’ultimo punto di codice è 65.535. Questi sono chiamati caratteri BMP (spiegati più avanti).
Con due unità di codice di UTF-16, possiamo codificare 1.048.576 caratteri. Dal momento che non possiamo ricominciare da 0 valore (punto di codice) perché questi vengono dopo i caratteri BMP, abbiamo bisogno di compensarli di 65.536. Questi caratteri sono chiamati caratteri supplementari (spiegati più avanti).
Quindi il primo carattere supplementare ha un valore del punto di codice di 65536 equivalent che è equivalente a 10000₁₆. Poiché possiamo codificare 1.048.576 caratteri con due unità di codice di UTF-16, l’ultimo punto di codice è 1114111₁₀ che equivale a 10FFFF₁₆.
Quindi scomponiamo le cose in una semplice forma tabellare.
+-----------+---------------------+--------------------+
| UTF-16 CU | Code Point | |
+-----------+---------------------+--------------------+
| 1 | 0000₁₆ - D7FF₁₆ | valid |
+-----------+---------------------+--------------------+
| 1 | D800₁₆ - DFFF₁₆ | invalid(surrogate) |
+-----------+---------------------+--------------------+
| 1 | E000₁₆ - FFFF₁₆ | valid |
+-----------+---------------------+--------------------+
| 2 | 10000₁₆ - 10FFFF₁₆ | valid |
+-----------+---------------------+--------------------+
| | 110000₁₆ - FFFFFF₁₆ | unassigned |
+-----------+---------------------+--------------------+
Con questa conoscenza, vediamo come possiamo codificare alcuni caratteri in UTF-16. Scegliamo un semplice carattere ASCII A (code point: 41₁₆), un carattere dalla lingua hindi (indiana) आ (pronunciato come Aa, code point: 906 point) e un’emoticon 😊 (chiamato come Happy face, code point: 1f60a₁₆).
Come possiamo vedere dalla tabella sopra, sia A che आ possono essere codificati in una sola unità di codice di UTF-16 poiché i loro valori sono inferiori a ffff₁₆.
Quando dobbiamo codificare un carattere in una sola unità di codice, dobbiamo solo convertire il punto di codice del carattere in un numero binario a 16 bit. Per i caratteri A, 00000000 01000001₂ è la rappresentazione UTF-16.
Allo stesso modo, per il carattere आ, abbiamo solo bisogno di convertire il suo punto di codice 906₁₆ in un numero binario a 16 bit che è 00001001 00000110₂.
Normalmente, rappresentiamo le unità di codice di un carattere in numeri esadecimali. Quindi per il carattere A, la rappresentazione UTF-16 è 0041₁₆ e allo stesso modo, per il carattere, la rappresentazione UTF-16 आ è 0906₁₆.
Per il personaggio 😊, le cose sono un po ‘ diverse. Il suo punto di codice è 1F60A₁₆. Se guardiamo la tabella UTF-16 menzionata sopra, deve essere codificata in 2 unità di codice di UTF-16. Allora, come cominciamo?
Per prima cosa, dobbiamo sottrarre 10000₁₆ dal punto di codice. La ragione di ciò è che ogni carattere codificato in 2 unità di codice di UTF-16 è arrivato dopo i caratteri BMP il cui ultimo punto di codice è FFFF₁₆.
Quindi per ottenere il valore effettivo dei bit utilizzati per la codifica (che è 20 in 2 unità di codice), dobbiamo sottrarre 10000₁₆ dal punto di codice e utilizzare il numero finale per generare questi 20 bit.
To Per aiutarti a capire meglio, il primo carattere rappresentato con 2 unità di codice di UTF-16 avrà tutti i suoi 20 bit impostati su 0. Quindi il valore dei bit utilizzati per codificare il punto di codice di questo carattere è 0. Ma ancora, il suo punto di codice è 10000 according secondo il set di caratteri Unicode. Questo perché il valore prodotto da questi 20 bit viene aggiunto a 10000₁₆ per generare il punto di codice finale.
Come visto in precedenza, queste 2 unità di codice appaiono come di seguito.
1101 10xx xxxx xxxx 1101 11xx xxxx xxxx
FIRST CODE UNIT---- SECOND CODE UNIT---
Abbiamo solo bisogno di riempire questi 20 bit (x
) con il valore ricevuto dal punto di codice del carattere. Il punto di codice del carattere 😊è 1f60a₁₆. Ma prima, dobbiamo sottrarre 10000 from da esso. Otteniamo F60A₁₆.
Ora dobbiamo convertire f60a₁₆ in un numero binario a 20 bit e riempire i 20 bit nel modello di unità di codice sopra. f60a₁₆ in binario è 0000111101 1000001010₂. Ora possiamo riempire questi 20 bit segnaposto.
Di seguito sono riportate le unità di codice finale.
1101 1000 0011 1101 1101 1110 0000 1010
0xD83D 0xDE0A
Il modo rapido per verificare se queste unità di codice sono valide e di fatto se queste coppie surrogate possono rappresentare il carattere codificato, aprire un DevTool del browser e inserireconsole.log('\uD83D\uDE0A');
nella console.
È inoltre possibile utilizzare questo strumento online per generare codice UTF-16 punti.
Piani di caratteri Unicode
Un piano è un gruppo continuo di 21 points o 65.536 punti di codice. Poiché UTF-16 ha limitato i punti di codice a un massimo di 10FFFF₁₆, abbiamo un totale di 17 piani di caratteri nello standard Unicode a partire da 0 a 16.
Poiché 21 characters caratteri possono essere definiti dalla singola unità di codice di UTF-16 (compresi i punti di codice surrogati), forma il primo (0°) piano. Questo piano contiene quasi tutti i personaggi nelle lingue di base in tutto il mondo. Questo è il motivo per cui questo piano è chiamato il piano multilingue di base o BMP.
Successivamente, abbiamo punti di codice definiti da due unità di codice di UTF-16. Questi contengono 22 characters caratteri poiché abbiamo 20 bit per codificare il valore del punto di codice. Questi sono divisi in 16 piani (2 x x 21.). Questi sono chiamati piani supplementari.
For Per ulteriori informazioni su questi piani, leggi questo documento di Wikipedia.
Confronto con UCS-2
UCS-2 è una codifica a larghezza fissa a 16 bit. Ciò significa che solo un’unità di codice a 16 bit viene utilizzata per rappresentare un punto di codice. In teoria, UCS-2 può rappresentare 21 characters caratteri distinti ma c’è una svolta.
BT A proposito, stiamo usando il termine unità di codice in questa codifica a larghezza fissa per comprendere la relazione tra UTF-16. In realtà, non esiste un’unità di codice in qualsiasi fissa con la codifica.
Poiché UCS segue il set di caratteri Unicode, la codifica dei caratteri in UCS-2 è identica alla codifica dei caratteri in UTF-16 che sono rappresentati in una sola unità di codice.
Since Poiché UCS segue il set di caratteri Unicode, non può codificare un carattere valido con i punti di codice riservati ai surrogati.
Quindi, in poche parole, UCS-2 contiene i caratteri del piano multilingue di base. Questo è il motivo per cui alcuni documenti più vecchi e il software utilizzavano la codifica UCS-2. Ma la codifica UCS-2 è diventata obsoleta e UTF-16 è preferito.
Endianness e BOM
Come abbiamo discusso prima, Un UTF codificato documenti su un basso livello contengono la sequenza di unità di codice. Per UTF-8, l’unità di codice è lunga 8 bit mentre per UTF-16 è lunga 16 bit. Queste unità di codice costituiscono i caratteri.
Un decodificatore UTF-8 o UTF-16 legge le unità di codice in sequenza, un’unità di codice alla volta per generare i caratteri.
Ogni unità di codice rappresenta un valore numerico che un decodificatore UTF-8 o UTF-16 può dare un’occhiata e decidere se è sufficiente rappresentare un carattere o segue altre unità di codice che dovrebbero essere considerate.
Quando si tratta di UTF-8, le cose sono semplici. Poiché ogni unità di codice è lunga 8 bit, convertire quel numero binario a 8 bit in un valore numerico è semplice e veloce. Questo non è il caso di UTF-16 però.
L’unità di codice UTF-16 è un numero binario a 16 bit (2 byte) che rappresenta un valore del punto di codice. Generare il valore numerico da più byte, in generale, è complicato e diversi sistemi si comportano in modo diverso.
Questo comportamento dipende dalla endianità del sistema. Dalla nostra precedente discussione sulla endianness, ci sono due modi in cui possiamo scrivere un valore unitario del codice UTF-16. In formato Big-endian o in formato Little-endian.
Nel formato Big-endian, MSB viene memorizzato per primo e LSB viene memorizzato per ultimo. Finora, stiamo scrivendo il valore unitario del codice UTF-16 nel formato Big-endian. Per scrivere il valore unitario del codice UTF-16 in Little-endian, dobbiamo scambiare i byte.
Parliamo di carattere आ. Dall’esempio precedente, può essere rappresentato in una sola unità di codice di UTF-16 e la sua codifica nella rappresentazione esadecimale sembra 0906₁₆.
0906 is è un numero a 16 bit con 09 come MSB e 06 come LSB. Quindi nell’architettura Big-endian, verrà memorizzato come 09 06. Tuttavia, in un’architettura Little-endian, verrà memorizzato come 06 09.
Quindi diventa nostra responsabilità codificare i caratteri prendendo in considerazione l’endianità del sistema in modo che il sistema possa leggere correttamente un documento UTF-16.
Ma come possiamo dire in anticipo se la macchina di un utente è compatibile con il documento codificato o meno? E poiché l’endianità di un sistema può influenzare il modo in cui un documento viene decodificato, come lo condividiamo pubblicamente?
Questo è dove BOM entra in scena. Un Byte Order Mark (BOM) è una sequenza di byte che viene aggiunta all’inizio di un file di testo o di dati di testo.
Unicode raccomanda il carattere con il punto di codice FEFF FE per fungere da distinta base per le codifiche UTF-16 e UTF-32. Questo carattere dovrebbe prima del primo carattere del documento. Tuttavia, questo carattere non sarà considerato dal decodificatore nell’output.
Questo carattere (U + FEFF)è un carattere ZWNBSP (non-breaking space) a larghezza zero ed è invisibile. Quindi, anche se un decodificatore non riesce a riconoscere la distinta base, non produrrà alcun output visibile.
Questo carattere è rappresentato in una singola unità di codice di UTF-16 e nella rappresentazione esadecimale sembra FE (MSB) e FF (LSB).
Quindi quando i caratteri sono codificati in formato Big-endian, dobbiamo aggiungere FEFF come distinta base all’inizio del file e quando i caratteri sono codificati in formato Little-endian, dobbiamo aggiungere FFFE (reverse) come distinta base all’inizio del file.
Unicode consiglia di aggiungere la distinta base al documento codificato UTF-16. Tuttavia, se manca la distinta base, viene assunto il formato Big-endian.
IANA preferisce UTF-16 come identificatore per indicare un documento codificato UTF-16. Tuttavia, UTF-16BE viene utilizzato per il documento codificato in formato Big-endian e UTF-16LE viene utilizzato per il formato Little-endian.
Quando viene utilizzato il nome UTF-16BE o UTF-16LE, non è consigliabile anteporre la distinta base a un file. Anche in questo caso, se viene aggiunta la distinta base, verrà considerata come carattere ZWNBSP e non verrà ignorata.
names UTF-16, UTF-16BE e UTF-16LE nomi sono case insensitive.
Pro e contro
UTF-16 è efficiente perché ha solo 2 unità di codice e poiché i caratteri più usati cadono nel set BMP, possono essere rappresentati in una sola unità di codice. Tuttavia, viene fornito con un sacco di problemi.
Il più grande svantaggio di UTF-16 è che non è compatibile con ASCII. Poiché i caratteri ASCII sono codificati con una singola unità di codice (numero a 16 bit), non possono essere decodificati correttamente da un decodificatore ASCII.
UTF-16 consuma spazio non necessario per i caratteri ASCII. Rispetto al documento codificato UTF-8 che contiene solo caratteri ASCII, la dimensione dello stesso documento codificato in UTF-16 è due volte più grande.
UTF-16 viene anche influenzato dalla endianità del sistema. Se manca la distinta base e non viene utilizzato un identificatore di codifica appropriato (come UTF-16LE), un documento codificato UTF-16 potrebbe non essere decodificato correttamente.
A causa della natura della codifica UTF-16, ha introdotto punti di codice surrogati che non possono rappresentare i caratteri validi. Inoltre, ha limitato il set di caratteri Unicode a 10ffff₁₆ (ultimo punto di codice).
Nonostante questi fatti, alcuni dei linguaggi di programmazione come JavaScript, Java, ecc. e sistemi come Windows preferiscono la codifica UTF-16.