Perché abbiamo bisogno di Unicode?
Agli albori (non troppo), tutto ciò che esisteva era ASCII. Questo andava bene, poiché tutto ciò che sarebbe mai stato necessario erano alcuni caratteri di controllo, punteggiatura, numeri e lettere come quelli in questa frase. Sfortunatamente, lo strano mondo odierno di intercomunicazione globale e social media non era previsto, e non è troppo insolito vedere inglese, inglese, spagnolo, ebraico, russo e ភាសាខ្មែរ nello stesso documento (spero di non aver rotto nessun vecchio i browser).
Ma per amor di sé, supponiamo che Joe Average sia uno sviluppatore di software. Insiste sul fatto che avrà sempre solo bisogno dell'inglese, e come tale vuole solo usare ASCII. Questo potrebbe andare bene per Joe l' utente , ma non va bene per Joe lo sviluppatore del software . Circa la metà del mondo usa caratteri non latini e l'uso dell'ASCII è probabilmente sconsiderato per queste persone, e per di più, sta chiudendo il suo software a un'economia grande e in crescita.
Pertanto, è necessario un set di caratteri comprensivo che includa tutte le lingue. Così è arrivato Unicode. Assegna a ogni carattere un numero univoco chiamato punto di codice . Un vantaggio di Unicode rispetto ad altri possibili set è che i primi 256 punti di codice sono identici a ISO-8859-1 , e quindi anche ASCII. Inoltre, la stragrande maggioranza dei caratteri comunemente usati è rappresentabile da soli due byte, in una regione chiamata Basic Multilingual Plane (BMP) . Ora è necessaria una codifica dei caratteri per accedere a questo set di caratteri e, man mano che la domanda si pone, mi concentrerò su UTF-8 e UTF-16.
Considerazioni sulla memoria
Quindi quanti byte danno accesso a quali caratteri in queste codifiche?
- UTF-8:
- 1 byte: ASCII standard
- 2 byte: arabo, ebraico, la maggior parte degli script europei (in particolare il georgiano escluso )
- 3 byte: BMP
- 4 byte: tutti i caratteri Unicode
- UTF-16:
- 2 byte: BMP
- 4 byte: tutti i caratteri Unicode
Vale la pena ricordare ora che i personaggi non inclusi nel BMP includono script antichi, simboli matematici, simboli musicali e caratteri cinesi / giapponesi / coreani (CJK) più rari .
Se lavorerai principalmente con caratteri ASCII, UTF-8 è sicuramente più efficiente in termini di memoria. Tuttavia, se lavori principalmente con script non europei, l'utilizzo di UTF-8 potrebbe essere fino a 1,5 volte meno efficiente in termini di memoria rispetto a UTF-16. Quando si ha a che fare con grandi quantità di testo, come pagine Web di grandi dimensioni o lunghi documenti di parole, ciò potrebbe influire sulle prestazioni.
Nozioni di base sulla codifica
Nota: se sai come sono codificati UTF-8 e UTF-16, passa alla sezione successiva per applicazioni pratiche.
- UTF-8: per i caratteri ASCII standard (0-127), i codici UTF-8 sono identici. Ciò rende UTF-8 ideale se è richiesta la retrocompatibilità con il testo ASCII esistente. Altri caratteri richiedono da 2 a 4 byte. Questo viene fatto riservando alcuni bit in ciascuno di questi byte per indicare che fa parte di un carattere multi-byte. In particolare, il primo bit di ogni byte è
1
evitare lo scontro con i caratteri ASCII.
- UTF-16: per caratteri BMP validi, la rappresentazione UTF-16 è semplicemente il suo punto di codice. Tuttavia, per i caratteri non BMP UTF-16 introduce coppie surrogate . In questo caso, una combinazione di due porzioni a due byte viene mappata su un carattere non BMP. Queste porzioni a due byte provengono dall'intervallo numerico BMP, ma sono garantite dallo standard Unicode come non valide come caratteri BMP. Inoltre, poiché UTF-16 ha due byte come unità di base, è influenzato dall'endianness . Per compensare, un contrassegno di ordine di byte riservato può essere posizionato all'inizio di un flusso di dati che indica endianness. Pertanto, se si sta leggendo l'input UTF-16 e non è stata specificata alcuna endianness, è necessario verificarlo.
Come si può vedere, UTF-8 e UTF-16 non sono quasi compatibili tra loro. Quindi, se stai eseguendo I / O, assicurati di sapere quale codifica stai usando! Per ulteriori dettagli su queste codifiche, consultare le FAQ UTF .
Considerazioni pratiche sulla programmazione
Tipi di dati carattere e stringa: come vengono codificati nel linguaggio di programmazione? Se sono byte non elaborati, nel momento in cui si tenta di generare caratteri non ASCII, è possibile che si verifichino alcuni problemi. Inoltre, anche se il tipo di carattere si basa su un UTF, ciò non significa che le stringhe siano UTF appropriate. Possono consentire sequenze di byte illegali. In genere, dovrai utilizzare una libreria che supporti UTF, come ICU per C, C ++ e Java. In ogni caso, se desideri inserire / emettere qualcosa di diverso dalla codifica predefinita, dovrai prima convertirla.
Codifiche consigliate / predefinite / dominanti: quando viene data la scelta di quale UTF utilizzare, di solito è meglio seguire gli standard raccomandati per l'ambiente in cui si sta lavorando. Ad esempio, UTF-8 è dominante sul web e, dal momento che HTML5, è stata la codifica consigliata . Al contrario, gli ambienti .NET e Java sono basati su un tipo di carattere UTF-16. Confusamente (e in modo errato), spesso si fa riferimento alla "codifica Unicode", che di solito si riferisce alla codifica UTF dominante in un determinato ambiente.
Supporto per le librerie : le librerie in uso supportano un tipo di codifica. Quale? Supportano i casi d'angolo? Poiché la necessità è la madre dell'invenzione, le librerie UTF-8 generalmente supporteranno correttamente i caratteri a 4 byte, poiché possono comparire frequentemente caratteri 1, 2 e persino 3 byte. Tuttavia, non tutte le presunte librerie UTF-16 supportano correttamente coppie surrogate poiché si verificano molto raramente.
Conteggio dei caratteri: esistono caratteri combinati in Unicode. Ad esempio il punto di codice U + 006E (n) e U + 0303 (una tilde combinante) forma ñ, ma il punto di codice U + 00F1 forma ñ. Dovrebbero apparire identici, ma un semplice algoritmo di conteggio restituirà 2 per il primo esempio, 1 per quest'ultimo. Questo non è necessariamente sbagliato, ma potrebbe anche non essere il risultato desiderato.
Confronto per l'uguaglianza: A, А e Α sembrano uguali, ma sono rispettivamente latino, cirillico e greco. Hai anche casi come C e Ⅽ, uno è una lettera, l'altro un numero romano. Inoltre, dobbiamo considerare anche i personaggi di combinazione. Per ulteriori informazioni, vedi Caratteri duplicati in Unicode .
Coppie surrogate: si presentano abbastanza spesso su SO, quindi fornirò solo alcuni link di esempio:
Altri?: