Differenza tra UTF-8 e UTF-16?


Risposte:


284

Credo che ci siano molti buoni articoli su questo in giro per il Web, ma ecco un breve riassunto.

Sia UTF-8 che UTF-16 sono codifiche di lunghezza variabile. Tuttavia, in UTF-8 un carattere può occupare un minimo di 8 bit, mentre in UTF-16 la lunghezza del carattere inizia con 16 bit.

Principali professionisti UTF-8:

  • I caratteri ASCII di base come cifre, caratteri latini senza accenti, ecc. Occupano un byte identico alla rappresentazione US-ASCII. In questo modo tutte le stringhe US-ASCII diventano UTF-8 valide, che in molti casi offrono una buona compatibilità con le versioni precedenti.
  • Nessun byte nullo, che consente di utilizzare stringhe con terminazione null, questo introduce anche una grande compatibilità con le versioni precedenti.
  • UTF-8 è indipendente dall'ordine dei byte, quindi non devi preoccuparti del problema di Big Endian / Little Endian.

Principali contro UTF-8:

  • Molti caratteri comuni hanno una lunghezza diversa, che rallenta l'indicizzazione in base al punto di codice e calcola terribilmente il conteggio di un punto di codice.
  • Anche se l'ordine dei byte non ha importanza, a volte UTF-8 ha ancora BOM (contrassegno dell'ordine dei byte) che serve a notificare che il testo è codificato in UTF-8 e rompe anche la compatibilità con il software ASCII anche se il testo contiene solo caratteri ASCII . Il software Microsoft (come Blocco note) ama in particolare aggiungere la distinta componenti a UTF-8.

Principali professionisti UTF-16:

  • Caratteri BMP (piano multilingue di base), tra cui latino, cirillico, la maggior parte dei cinesi (la RPC ha reso obbligatorio il supporto di alcuni punti di codice al di fuori di BMP), la maggior parte dei giapponesi può essere rappresentata con 2 byte. Ciò accelera l'indicizzazione e il calcolo del conteggio dei punti di codice nel caso in cui il testo non contenga caratteri supplementari.
  • Anche se il testo ha caratteri supplementari, sono comunque rappresentati da coppie di valori a 16 bit, il che significa che la lunghezza totale è ancora divisibile per due e consente di utilizzare 16 bit charcome componente primitivo della stringa.

Principali contro UTF-16:

  • Molti byte null nelle stringhe US-ASCII, il che significa che non ci sono stringhe con terminazione null e molta memoria sprecata.
  • Usarlo come codifica a lunghezza fissa “funziona principalmente” in molti scenari comuni (specialmente negli Stati Uniti / UE / paesi con alfabeti cirillici / Israele / Paesi arabi / Iran e molti altri), portando spesso a un supporto rotto dove non lo fa. Ciò significa che i programmatori devono essere consapevoli delle coppie surrogate e gestirle correttamente nei casi in cui è importante!
  • Ha una lunghezza variabile, quindi il conteggio o l'indicizzazione dei punti di codice è costoso, sebbene inferiore a UTF-8.

In generale, UTF-16 è di solito migliore per la rappresentazione in memoria perché BE / LE è irrilevante lì (basta usare l'ordine nativo) e l'indicizzazione è più veloce (basta non dimenticare di gestire correttamente le coppie surrogate). UTF-8, d'altra parte, è estremamente buono per file di testo e protocolli di rete perché non vi è alcun problema BE / LE e la terminazione null spesso è utile, così come la compatibilità ASCII.


3
Manca solo la parte BE / LE su UTF16 :) UTF-8 ha un altro aspetto negativo, potrebbe generare un output più lungo rispetto a UTF16
bestsss

4
Sì, mi sono dimenticato di BE / LE. Non è un grosso problema, tuttavia, soprattutto per l'uso in memoria. UTF-8 genererà un output più lungo solo se sono coinvolti caratteri a tre byte, ma ciò significa principalmente cinese e giapponese. D'altra parte, se il testo contiene molti caratteri US-ASCII, può generare un output più breve, quindi se è un aspetto negativo o no dipende da una situazione particolare.
Sergei Tachenov,

Non ho nemmeno pensato di menzionare l'immediato pro di utf-8, di lunghezza inferiore. Circa l'output più lungo di utf-8 era "può" per una ragione, ma se il target è molto più a est, la codifica predefinita dovrebbe essere utf-16. Come nell'esempio md.update (text.getBytes ("UTF-8")); la codifica non ha importanza poiché l'hash è stabile in entrambi i modi.
bestsss

Il modo più veloce per convertire String in array di byte è qualcosa del genere, pubblicato come campione
bestsss

Dici che i caratteri hanno una lunghezza diversa in UTF-8, quindi rallenta l'indicizzazione e il calcolo della lunghezza, ma dubito che anche i caratteri in UTF-16 abbiano una lunghezza diversa, l'indicizzazione e il calcolo della lunghezza di UTF-16 dovrebbero essere più veloci?
nicky_zs

19

Sono semplicemente schemi diversi per rappresentare i personaggi Unicode.

Entrambi sono di lunghezza variabile - UTF-16 utilizza 2 byte per tutti i caratteri nel piano multilingue di base (BMP) che contiene la maggior parte dei caratteri di uso comune.

UTF-8 utilizza tra 1 e 3 byte per i caratteri nel BMP, fino a 4 per i caratteri nell'intervallo Unicode corrente da U + 0000 a U + 1FFFFF, ed è estendibile fino a U + 7FFFFFFF se ciò diventa mai necessario ... ma in particolare tutti i caratteri ASCII sono rappresentati in un singolo byte ciascuno.

Ai fini di un digest del messaggio non importa quale di questi scegli, purché tutti coloro che provano a ricreare il digest utilizzino la stessa opzione.

Vedi questa pagina per ulteriori informazioni su UTF-8 e Unicode.

(Notare che tutti i caratteri Java sono punti di codice UTF-16 all'interno del BMP; per rappresentare i caratteri sopra U + FFFF è necessario utilizzare coppie surrogate in Java.)


5

Sicurezza: utilizzare solo UTF-8

Differenza tra UTF-8 e UTF-16? Perché ne abbiamo bisogno?

Ci sono state almeno un paio di vulnerabilità di sicurezza nelle implementazioni di UTF-16 . Vedi Wikipedia per i dettagli .

WHATWG e W3C hanno ora dichiarato che solo UTF-8 deve essere utilizzato sul Web.

I problemi di [sicurezza] qui descritti scompaiono quando si utilizza esclusivamente UTF-8, che è uno dei tanti motivi che ora è la codifica obbligatoria per tutte le cose.

Altri gruppi stanno dicendo lo stesso.

Quindi, mentre UTF-16 può continuare ad essere utilizzato internamente da alcuni sistemi come Java e Windows, il poco uso di UTF-16 che potresti aver visto in passato per file di dati, scambio di dati e simili, probabilmente svanirà del tutto.


4

Questo non è correlato a UTF-8/16 (in generale, anche se viene convertito in UTF16 e la parte BE / LE può essere impostata con una sola riga), tuttavia di seguito è il modo più veloce per convertire String in byte []. Ad esempio: buono esattamente per il caso fornito (codice hash). String.getBytes (enc) è relativamente lento.

static byte[] toBytes(String s){
        byte[] b=new byte[s.length()*2];
        ByteBuffer.wrap(b).asCharBuffer().put(s);
        return b;
    }

-3

Un modo semplice per differenziare UTF-8 e UTF-16 è identificare i punti in comune tra loro.

Oltre a condividere lo stesso numero unicode per un determinato personaggio, ognuno ha il proprio formato.

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.