2012-05-16 9 views
25

Sono abbastanza confuso riguardo al concetto di codifica dei caratteri .Cos'è la codifica dei caratteri e perché dovrei preoccuparmene

Che cos'è Unicode, GBK, ecc.? Come li usa un linguaggio di programmazione?

Devo preoccuparmi di conoscerli? C'è un modo più semplice o più veloce di programmazione senza dovermi preoccupare di loro?

+6

La classica risorsa fuori sito per questo è il saggio di Joel Spolsky [_Lo Sviluppatore Absolute Minimum Every Software assolutamente e positivamente deve conoscere Unicode e Set di caratteri (nessuna scusa!) _] (Http://www.joelonsoftware.com/ articoli/Unicode.html). – Raedwald

+1

È una risposta tardiva, ma ho postato alcune spiegazioni sulle codifiche e sui set di caratteri citati + anche alcune scorciatoie (ad esempio per Java) – bvdb

risposta

27

(Si noti che sto usando alcuni di questi termini vagamente/colloquialmente per una spiegazione più semplice che colpisce ancora i punti chiave.)

Un byte può avere solo 256 valori distinti, essendo 8 bit.

Poiché ci sono set di caratteri con più di 256 caratteri nel set di caratteri, non si può in generale dire semplicemente che ogni carattere è un byte.

Pertanto, ci devono essere mappature che descrivono come trasformare ciascun carattere in un set di caratteri in una sequenza di byte. Alcuni caratteri potrebbero essere associati a un singolo byte, ma altri dovranno essere mappati su più byte.

Queste mappature sono codifiche, perché indicano come codificare i caratteri in sequenze di byte.

Come Unicode, ad un livello molto elevato, Unicode è un tentativo di assegnare un singolo numero univoco a ogni carattere. Ovviamente quel numero deve essere qualcosa di più ampio di un byte dato che ci sono più di 256 caratteri :) Java usa una versione di Unicode in cui a ogni personaggio è assegnato un valore a 16 bit (ed è per questo che i caratteri Java sono larghi 16 bit e hanno numero intero valori da 0 a 65535). Quando ottieni la rappresentazione in byte di un carattere Java, devi dire alla JVM la codifica che vuoi usare in modo che sappia come scegliere la sequenza di byte per il personaggio.

2

La codifica dei caratteri è ciò che si utilizza per risolvere il problema della scrittura di software per qualcuno che utilizza una lingua diversa da quella dell'utente.

Non sai come sono i personaggi e come sono ordinati. Pertanto, non sai come saranno le stringhe in questa nuova lingua in binario e francamente, non ti interessa.

Quello che hai è un modo di tradurre stringhe dalla lingua che parli alla lingua che parlano (ad esempio un traduttore). Ora hai bisogno di un sistema in grado di rappresentare entrambe le lingue in binario senza conflitti. La codifica è quel sistema.

È ciò che consente di scrivere software che funziona indipendentemente dal modo in cui le lingue sono rappresentate in binario.

22

ASCII è fondamentale

Originariamente 1 personaggio è sempre memorizzato come 1 byte. Un byte (8 bit) ha il potenziale per distinguere 256 possibili valori. Ma in effetti sono stati utilizzati solo i primi 7 bit. Quindi sono stati definiti solo 128 caratteri. Questo set è noto come il set di caratteri ASCII.

  • 0x00 - 0x1F contengono codici di sterzo (ad esempio CR, LF, STX, ETX, EOT, BEL, ...)
  • 0x20-0x40 contenere numeri e segni di punteggiatura
  • 0x41 - 0x7F contengono caratteri alfabetici per lo più
  • 0x80 - 0xFF l'8 bit = undefined.

Francese, tedesco e molte altre lingue richiedevano caratteri aggiuntivi. (ad esempio à, é, ç, ô, ...) che non erano disponibili nel set di caratteri ASCII. Quindi hanno usato l'ottavo bit per definire i loro personaggi. Questo è noto come "ASCII esteso".

Il problema è che l'ulteriore 1 bit non ha abbastanza capacità per coprire tutte le lingue del mondo. Quindi ogni regione ha la sua variante ASCII. Ci sono molte codifiche ASCII estese (latin-1 è molto popolare).

domanda popolare: "è ASCII set di caratteri o è una codifica"? ASCII è un set di caratteri. Tuttavia, nella programmazione charset e encoding vengono utilizzati come sinonimi. Se voglio fare riferimento a una codifica che contiene solo i caratteri ASCII e nulla più (l'8 ° bit è sempre 0): è US-ASCII.

Unicode va oltre

Unicode è anche un set di caratteri (non una codifica). Utilizza gli stessi caratteri come lo standard ASCII, ma estende l'elenco con caratteri aggiuntivi, che assegnano a ciascun carattere un punto di codice nel formato u+xxxx. Ha l'ambizione di contenere tutti i personaggi (e le icone popolari) utilizzati in tutto il mondo.

UTF-8, UTF-16 e UTF-32 sono codifiche che applicano la tabella di caratteri Unicode. Ma ognuno di loro ha un modo leggermente diverso su come codificarli. UTF-8 utilizzerà solo 1 byte durante la codifica di un carattere ASCII, fornendo lo stesso risultato di qualsiasi altra codifica ASCII. Ma per gli altri caratteri, utilizzerà il primo bit per indicare che seguirà un secondo byte.

GBK è una codifica, che proprio come UTF-8 utilizza più byte. Il primo byte segue lo standard ASCII, quindi vengono utilizzati solo 7 bit. L'8 ° bit viene utilizzato per indicare la presenza di un 2 ° byte, che viene utilizzato per rappresentare circa 22.000 caratteri cinesi. Ma una differenza importante, è che questo non rispetta il set di caratteri Unicode.

tipi Mime

tipi MIME sono anche spesso confuso con codifiche.

Non esiste un modo semplice per decodificare un file. Sarebbe stato ideale se tutti i file contenessero un prefisso per indicare la codifica dei dati in cui erano memorizzati. Alla fine spetta all'applicazione (o al suo sviluppatore) determinare una codifica (ad esempio US-ASCII, UTF-8, alcuni valori di default del sistema. ..).

Quando si inviano dati su Internet esiste lo stesso problema.Per fortuna alcuni protocolli come HTTP usano dichiarazioni di tipo mime per specificare quale tipo di dati e charset i dati utilizzano. Un tipico intestazione HTTP contiene questo:

Content-Type: text/html; charset=utf-8 

Ma per text/xml che sarebbe inutile (un parametro charset sarà nemmeno essere ignorato). I parser XML in generale leggeranno la prima riga del file, cercando il tag <?xml encoding=.... Se è lì, riaprirà il file usando quella codifica.

Lo stesso problema esiste when sending e-mails. Una e-mail può contenere un messaggio html o semplicemente testo.

Scorciatoie

In caso di Java (e molti altri linguaggi di programmazione), oltre ai pericoli di codifiche, c'è anche la complessità della fusione byte e numeri interi in caratteri perché il loro contenuto è memorizzato in diverse categorie.

  • un byte viene memorizzato come un byte con segno (range: -128 a 127).
  • tipo char in java è memorizzato in 2 byte senza segno (range: 0 - 65535)
  • un flusso restituisce un numero intero nella gamma -1 a 255.

Se si sa che i dati contengono solo valori ASCII. Quindi con l'abilità appropriata è possibile analizzare i dati da byte a caratteri o avvolgerli immediatamente in Stringhe.

// the -1 indicates that there is no data 
int input = stream.read(); 
if (input == -1) throw new EOFException(); 

// bytes must be made positive first. 
byte myByte = (byte) input; 
int unsignedInteger = myByte & 0xFF; 
char ascii = (char)(unsignedInteger); 

Il collegamento in Java è quello di utilizzare i lettori e scrittori e per specificare la codifica quando li si crea un'istanza.

// wrap your stream in a reader. 
// specify the encoding 
// The reader will decode the data for you 
Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); 

Come spiegato in precedenza per i file XML non importa più di tanto, perché qualsiasi DOM decente o JAXB marshaller verifica la presenza di un attributo di codifica.

+1

Solo una piccola nota: Poiché quasi tutte le codifiche codificano i 128 caratteri ASCII di base allo stesso modo, a lungo poiché tutti i caratteri utilizzati sono definiti in questo set di base, puoi effettivamente codificare/decodificare il tuo messaggio usando quasi tutte le codifiche casuali. (ad esempio UTF-8, US-ASCII, latin-1, GBK, ...). – bvdb

+1

Interessante anche il BOM (byte-order-mark) che viene utilizzato per le codifiche che utilizzano più byte (ad esempio UTF-16). Indica quale dei byte è il primo (il più significativo). Questo byte-marcatore è messo davanti al messaggio. Un altro buon motivo per usare 'Reader's decenti. – bvdb

+0

La tabella dei caratteri di Unicode * è * una codifica per definizione, tuttavia è doppia codificata in i. e. UTF-8. Quindi è semplicemente sbagliato, che Unicode non abbia codifica. –

Problemi correlati