Commenti
- Non proprio corretto. Spiego, se scrivi " שָׁ " il carattere composto che consiste di " ש ", " ָ " e " ׁ ", vovels, quindi la rimozione di ciascuno di essi è logica, rimuovi un punto di codice quando premi " backspace " e rimuovi tutti i caratteri inclusi i vovels quando premi " del ". Tuttavia, non produci mai uno stato del testo illegale : punti di codice illegali. Pertanto, la situazione in cui si preme Backspace e si ottiene un testo illegale non è corretta.
- CiscoIPPhone: se un bug viene " segnalato più volte, da molte persone diverse ", e poi un paio di anni dopo uno sviluppatore scrive su un blog di sviluppo che " Che tu ci creda o no, il comportamento è per lo più intenzionale! ", quindi (per usare un eufemismo) tendo a pensare che ' non sia probabilmente la migliore decisione di progettazione mai presa. 🙂 Solo perché ' è intenzionale ' non significa ' un bug.
- Ottimo post. UTF-16 è effettivamente il " peggiore dei due mondi ": UTF8 è di lunghezza variabile, copre tutto Unicode, richiede un algoritmo di trasformazione da e verso punti di codice grezzi, si limita ad ASCII e non ha problemi di endianness. UTF32 è di lunghezza fissa, non richiede alcuna trasformazione, ma occupa più spazio e presenta problemi di endianness. Fin qui tutto bene, puoi usare UTF32 internamente e UTF8 per la serializzazione. Ma UTF16 non ha vantaggi: ' è dipendente da endian, è ' è di lunghezza variabile, occupa molto spazio, ' non è compatibile con ASCII. Lo sforzo necessario per gestire correttamente UTF16 potrebbe essere speso meglio su UTF8.
- @Ian: UTF-8 NON ha gli stessi avvertimenti di UTF-8. Non puoi avere surrogati in UTF-8. UTF-8 non si maschera come qualcosa che non è, ma la maggior parte dei programmatori che utilizzano UTF-16 lo stanno usando in modo sbagliato. Lo so. ' li ho guardati ancora e ancora e ancora e ancora.
- Inoltre, UTF-8 non ' t hanno il problema perché tutti la trattano come una codifica a larghezza variabile. Il motivo per cui UTF-16 ha il problema è perché tutti lo considerano come una codifica a larghezza fissa.
Risposta
Questa è una vecchia risposta.
Vedi UTF-8 Everywhere per gli ultimi aggiornamenti.
Opinione: Sì, UTF-16 dovrebbe essere considerato dannoso . La vera ragione per cui esiste è perché qualche tempo fa cera una convinzione errata che widechar sarebbe stato ciò che UCS-4 ora è.
Nonostante l “anglo-centrismo” di UTF-8, dovrebbe essere considerata lunica codifica utile per il testo. Si può sostenere che i codici sorgente di programmi, pagine web e file XML, nomi di file del sistema operativo e altre interfacce di testo da computer a computer non avrebbero mai dovuto esistere. Ma quando lo fanno, il testo non è solo per i lettori umani.
Daltra parte, loverhead UTF-8 è un piccolo prezzo da pagare mentre presenta vantaggi significativi. Vantaggi come la compatibilità con codice inconsapevole che passa solo stringhe con char*
. Questa è una grande cosa. Ci sono pochi caratteri utili PIÙ CORTI in UTF-16 di quanto lo siano in UTF-8.
Credo che tutte le altre codifiche alla fine moriranno. Ciò implica che MS-Windows, Java, ICU, python smettere di usarlo come il loro preferito. Dopo lunghe ricerche e discussioni, le convenzioni di sviluppo in la mia azienda vietano luso di UTF-16 ovunque eccetto le chiamate API del sistema operativo, e questo nonostante limportanza di prestazioni nelle nostre applicazioni e il fatto che utilizziamo Windows. Le funzioni di conversione sono state sviluppate per convertire std::string
in UTF-16 nativo, che Windows stesso non supporta correttamente .
A chi dice “ usa ciò che serve dove è necessario “, io dico: “cè un enorme vantaggio nellusare la stessa codifica ovunque, e non vedo ragioni sufficienti per In particolare, penso che laggiunta di wchar_t
a C ++ sia stato un errore, così come le aggiunte Unicode a C ++ 0x. Ciò che deve essere richiesto dalle implementazioni STL è che ogni Il parametro std::string
o char*
sarebbe considerato compatibile con Unicode.
Sono anche contrario all “ utilizzo quello che vuoi “. Non vedo alcun motivo per tale libertà. Cè abbastanza confusione sullargomento del testo, con il risultato di tutto questo software rotto. Detto sopra, sono convinto che i programmatori debbano finalmente raggiungere il consenso su UTF-8 come un modo corretto. (Vengo da un paese che non parla ascii e sono cresciuto con Windows, quindi mi sarei aspettato che attaccasse UTF-16 per motivi religiosi).
Vorrei condividere più informazioni su come eseguo il testo su Windows, e cosa consiglio a tutti gli altri per la correttezza unicode verificata in fase di compilazione, la facilità duso e una migliore multi-piattaforma del codice. Il suggerimento è sostanzialmente diverso da quello che di solito è raccomandato come modo corretto di usare Unicode su Windows. Tuttavia, una ricerca approfondita di queste raccomandazioni ha portato alla stessa conclusione. Quindi ecco qui:
- Non utilizzare
wchar_t
ostd::wstring
in qualsiasi luogo diverso dal punto adiacente a API che accettano UTF-16. - Non utilizzare
_T("")
oL""
UTF-16 letterali (questi dovrebbero essere presi IMO dallo standard , come parte della deprecazione UTF-16). - Non utilizzare tipi, funzioni o loro derivati sensibili alla costante
_UNICODE
, comeLPTSTR
oCreateWindow()
. - Tuttavia,
_UNICODE
sempre definito, per evitare di passare le stringhechar*
a WinAPI che viene compilato silenziosamente -
std::strings
echar*
ovunque nel programma sono considerati UTF-8 (se non diversamente specificato) - Tutte le mie stringhe sono
std::string
, anche se puoi passare char * o stringa letterale aconvert(const std::string &)
. -
utilizza solo funzioni Win32 che accettano widechars (
LPWSTR
). Mai quelli che accettanoLPTSTR
oLPSTR
. Passa i parametri in questo modo:::SetWindowTextW(Utils::convert(someStdString or "string litteral").c_str())
(la norma utilizza le funzioni di conversione di seguito).
-
Con stringhe MFC :
CString someoneElse; // something that arrived from MFC. Converted as soon as possible, before passing any further away from the API call: std::string s = str(boost::format("Hello %s\n") % Convert(someoneElse)); AfxMessageBox(MfcUtils::Convert(s), _T("Error"), MB_OK);
-
Lavorare con file, nomi di file e fstream su Windows:
- Non passare mai
std::string
oconst char*
argomenti nome file per la famigliafstream
. MSVC STL non supporta gli argomenti UTF-8, ma ha unestensione non standard che dovrebbe essere utilizzata come segue: -
Converti
std::string
argomenti instd::wstring
conUtils::Convert
:std::ifstream ifs(Utils::Convert("hello"), std::ios_base::in | std::ios_base::binary);
Dobbiamo “farlo manualmente rimuovere la conversione, quando latteggiamento di MSVC nei confronti di
fstream
cambia. - Questo codice non è multipiattaforma e potrebbe essere necessario modificarlo manualmente in il futuro
- Vedi
fstream
caso di ricerca / discussione unicode 4215 per maggiori informazioni. - Non produrre mai file di output di testo con contenuto non UTF8
- Evita di utilizzare
fopen()
per motivi RAII / OOD. Se necessario, utilizza le_wfopen()
e le convenzioni WinAPI sopra.
- Non passare mai
// For interface to win32 API functions std::string convert(const std::wstring& str, unsigned int codePage /*= CP_UTF8*/) { // Ask me for implementation.. ... } std::wstring convert(const std::string& str, unsigned int codePage /*= CP_UTF8*/) { // Ask me for implementation.. ... } // Interface to MFC std::string convert(const CString &mfcString) { #ifdef UNICODE return Utils::convert(std::wstring(mfcString.GetString())); #else return mfcString.GetString(); // This branch is deprecated. #endif } CString convert(const std::string &s) { #ifdef UNICODE return CString(Utils::convert(s).c_str()); #else Exceptions::Assert(false, "Unicode policy violation. See W569"); // This branch is deprecated as it does not support unicode return s.c_str(); #endif }
Commenti
- Non posso ' essere daccordo. I vantaggi di utf16 rispetto a utf8 per molte lingue asiatiche dominano completamente i punti che fai. È ingenuo sperare che i giapponesi, i thailandesi, i cinesi, ecc. Rinuncino a questa codifica. Gli scontri problematici tra i set di caratteri si verificano quando i set di caratteri sembrano per lo più simili, tranne che con differenze. Suggerisco di standardizzare su: fisso 7bit: iso-irv-170; Variabile a 8 bit: utf8; Variabile a 16 bit: utf16; 32 bit fisso: ucs4.
- @Charles: grazie per il tuo contributo. È vero, alcuni caratteri BMP sono più lunghi in UTF-8 che in UTF-16. Ma lascia che ' lo faccia: il problema non è nei byte che prendono i caratteri cinesi BMP, ma nella complessità di progettazione del software che ne deriva. Se un programmatore cinese deve comunque progettare caratteri di lunghezza variabile, sembra che UTF-8 sia ancora un piccolo prezzo da pagare rispetto ad altre variabili del sistema. Potrebbe usare UTF-16 come algoritmo di compressione se lo spazio è così importante, ma anche in questo caso non corrisponderà a LZ, e dopo LZ o unaltra compressione generica hanno entrambi circa la stessa dimensione ed entropia.
- Quello che sostanzialmente dico è che la semplificazione offerta dallavere una codifica compatibile anche con i programmi char * esistenti, ed è anche la più popolare oggi per tutto è inimmaginabile.È quasi come ai bei vecchi " testo normale " giorni. Vuoi aprire un file con un nome? Non cè bisogno di preoccuparsi del tipo di unicode che stai facendo, ecc. Ecc. Suggerisco a noi sviluppatori di limitare UTF-16 a casi molto speciali di ottimizzazione severa in cui un po di prestazioni vale mesi-uomo di lavoro.
- Linux ha avuto un requisito specifico quando ha scelto di utilizzare UTF-8 internamente: compatibilità con Unix. Windows non ' ne aveva bisogno, e quindi quando gli sviluppatori hanno implementato Unicode, hanno aggiunto le versioni UCS-2 di quasi tutte le funzioni che gestiscono il testo e hanno convertito quelle multibyte in UCS-2 e chiama gli altri. Successivamente sostituisce UCS-2 con UTF-16. Linux daltra parte ha mantenuto le codifiche a 8 bit e quindi ha utilizzato UTF-8, poiché ' è la scelta corretta in quel caso.
- @Pavel Radzivilovsky : BTW, i tuoi scritti su " credo che tutte le altre codifiche alla fine moriranno. Ciò implica che MS-Windows, Java, ICU e python smettono di utilizzarli come preferiti. " e " In particolare, penso che laggiunta di wchar_t a C ++ sia stato un errore, così come le aggiunte Unicode a C ++ Ox. " sono piuttosto ingenue o molto molto arroganti . E questo viene da qualcuno che codifica a casa con un Linux e che è contento dei caratteri UTF-8. Per dirla senza mezzi termini: non ' accadrà .
Risposta
I punti di codice Unicode non sono caratteri! A volte non sono nemmeno glifi (forme visive) .
Alcuni esempi:
- Punti di codice in numeri romani come “ⅲ”. (Un singolo carattere che assomiglia a “iii”.)
- Caratteri accentati come “á”, che possono essere rappresentati come un singolo carattere combinato “\ u00e1” o un carattere e segni diacritici separati “\ u0061 \ u0301 “.
- Caratteri come il sigma minuscolo greco, che hanno forme diverse per la posizione centrale (” σ “) e finale (” ς “) delle parole, ma che dovrebbero essere considerati sinonimi per la ricerca.
- Trattino discrezionale Unicode U + 00AD, che potrebbe o non potrebbe essere visualizzato visivamente, a seconda del contesto, e che viene ignorato per la ricerca semantica.
Gli unici modi per ottenere la modifica Unicode è giusto utilizzare una libreria scritta da un esperto , oppure diventare un esperto e scriverne una tu stesso. Se stai solo contando i punti di codice, stai vivendo in uno stato di peccato.
Commenti
- Questo. Molto questo. UTF-16 può causare problemi, ma anche luso di UTF-32 può (e lo farà) comunque darti problemi.
- Cosè un carattere? Puoi definire un punto di codice come un carattere e cavartela abbastanza bene. Se intendi un glifo visibile dallutente, è qualcosaltro.
- @tchrist sicuro per lallocazione dello spazio quella definizione va bene, ma per qualcosaltro? Non così tanto. Se gestisci un carattere di combinazione come unico carattere (ad esempio per unoperazione di eliminazione o " prendi i primi N caratteri "), ' otterrai un comportamento strano e sbagliato. Se un punto di codice ha significato solo se combinato con almeno un altro, puoi ' gestirlo da solo in modo ragionevole.
- @Pacerier, questo è tardi alla festa, ma devo commentare su questo. Alcune lingue hanno insiemi molto ampi di potenziali combinazioni di segni diacritici (c.f. vietnamita, cioè mệt đừ). È molto utile avere combinazioni anziché un carattere per diacritico.
- una piccola nota sulla terminologia: i punti di codice fanno corrispondono a caratteri unicode ; ciò di cui parla Daniel qui sono caratteri percepiti dagli utenti , che corrispondono a cluster grafema unicode
Risposta
Esiste una semplice regola pratica su quale Unicode Transformation Form (UTF) usare: – utf-8 per larchiviazione e la comunicazione – utf-16 per lelaborazione dei dati – potresti andare con utf-32 se la maggior parte delle API della piattaforma che utilizzi è utf-32 (comune nel mondo UNIX).
La maggior parte dei sistemi oggi utilizza utf-16 (Windows, Mac OS, Java, .NET, ICU , Qt). Consulta anche questo documento: http://unicode.org/notes/tn12/
Torna a “UTF-16 as dangerous”, Direi: assolutamente no.
Le persone che hanno paura dei surrogati (pensando di trasformare Unicode in una codifica a lunghezza variabile) non capiscono le altre complessità (molto più grandi) che rendono la mappatura tra caratteri e un punto di codice Unicode molto complesso: combinazione di caratteri, legature, selettori di variazione, caratteri di controllo, ecc.
Basta leggere questa serie qui http://www.siao2.com/2009/06/29/9800913.aspx e guarda come UTF-16 diventa un problema facile.
Commenti
- Per favore aggiungi alcuni esempi in cui UTF-32 è comune nel mondo UNIX!
- No, non lo fai desidera utilizzare UTF-16 per lelaborazione dei dati. ' è un rompicoglioni. Ha tutti gli svantaggi di UTF-8 ma nessuno dei suoi vantaggi. Sia UTF-8 che UTF-32 sono chiaramente superiori al vizioso hack precedentemente noto come Mrs UTF-16, il cui nome da nubile era UCS-2.
- Ieri ho appena trovato un bug nella classe Java core Strings
equalsIgnoreCase
(anche altri nella classe string) che non sarebbe mai esistito se Java avesse utilizzato UTF-8 o UTF-32. Ci sono milioni di queste bombe dormienti in qualsiasi codice che utilizza UTF-16, e io sono stufo e stanco di loro. UTF-16 è un vizioso vaiolo che affligge il nostro software con bug insidiosi per sempre. È chiaramente dannoso e dovrebbe essere deprecato e bandito. - @tchrist Wow quindi una funzione consapevole non surrogata (perché è stata scritta quando non ce nerano ed è purtroppo documentata in modo tale da renderla probabilmente impossibile adattare – specifica che .toUpperCase (char)) comporterà il comportamento sbagliato? ' sei consapevole del fatto che una funzione UTF-32 con una mappa di punti di codice obsoleta ' non gestirà meglio questa situazione? Inoltre lintera API Java gestisce i surrogati non particolarmente bene e i punti più intricati su Unicode per niente – e con il successivo la codifica utilizzata non ' sarebbe affatto importante.
- -1: Un
.Substring(1)
incondizionato in .NET è un banale esempio di qualcosa che interrompe il supporto per tutti gli Unicode non BMP. Tutto che utilizza UTF-16 ha questo problema; ' è troppo facile trattarla come una codifica a larghezza fissa e si riscontrano problemi troppo raramente. Ciò la rende una codifica attivamente dannosa se si desidera supportare Unicode.
Risposta
Sì, assolutamente.
Perché? Ha a che fare con l esercizio del codice .
Se guardi queste statistiche sullutilizzo dei punti di codice su un ampio corpus di Tom Christiansen vedrai che i punti di codice BMP trans-8 bit vengono utilizzati di diversi ordini se di grandezza maggiore dei punti di codice non BMP:
2663710 U+002013 ‹–› GC=Pd EN DASH 1065594 U+0000A0 ‹ › GC=Zs NO-BREAK SPACE 1009762 U+0000B1 ‹±› GC=Sm PLUS-MINUS SIGN 784139 U+002212 ‹−› GC=Sm MINUS SIGN 602377 U+002003 ‹ › GC=Zs EM SPACE 544 U+01D49E ‹𝒞› GC=Lu MATHEMATICAL SCRIPT CAPITAL C 450 U+01D4AF ‹𝒯› GC=Lu MATHEMATICAL SCRIPT CAPITAL T 385 U+01D4AE ‹𝒮› GC=Lu MATHEMATICAL SCRIPT CAPITAL S 292 U+01D49F ‹𝒟› GC=Lu MATHEMATICAL SCRIPT CAPITAL D 285 U+01D4B3 ‹𝒳› GC=Lu MATHEMATICAL SCRIPT CAPITAL X
Prendi il motto TDD: “Il codice non testato è un codice non funzionante” e riformulalo come “il codice non esercitato è un codice non funzionante” e pensa quanto spesso i programmatori hanno a che fare con codepoint non BMP.
È molto più probabile che i bug relativi al non trattare con UTF-16 come codifica a larghezza variabile passino inosservati rispetto ai bug equivalenti in UTF-8 . Alcuni linguaggi di programmazione ancora non ti garantisci di darti UTF-16 invece di UCS-2, e alcuni cosiddetti linguaggi di programmazione di alto livello offrono accesso alle unità di codice invece che ai punti di codice (anche C dovrebbe darti accesso ai punti di codice se usi wchar_t
, a prescindere da ciò che alcuni plat moduli possono andare bene).
Commenti
- " Bug relativi al non trattare con UTF-16 come è molto più probabile che una codifica a larghezza variabile passi inosservata rispetto ai bug equivalenti in UTF-8. " Questo è il nocciolo del problema e, quindi, la risposta corretta.
- Esatto. Se la tua gestione UTF-8 è disturbata, ' sarà immediatamente evidente. Se la tua gestione UTF-8 è disturbata, ' noterai solo se inserisci caratteri Han o simboli matematici non comuni.
- Molto vero, ma daltro canto a cosa servono gli unit test se dovessi dipendere dalla fortuna per trovare bug in casi meno frequenti?
- @musiphil: allora, quando è stata lultima volta che hai creato uno unit test per caratteri non BMP?
- Per approfondire la mia precedente affermazione: anche con UTF-8, non puoi essere certo di aver coperto tutti i casi dopo aver visto solo alcuni esempi funzionanti. Lo stesso con UTF-16: devi verificare se il tuo codice funziona sia con i non surrogati che con i surrogati. (Qualcuno potrebbe anche sostenere che UTF-8 ha almeno quattro casi principali mentre UTF-16 ne ha solo due.)
Risposta
Suggerirei che pensare che UTF-16 possa essere considerato dannoso dica che è necessario acquisire una maggiore comprensione di unicode .
Dato che sono stato sottovalutato per aver presentato la mia opinione su una domanda soggettiva, lasciami elaborare. Cosè esattamente che ti infastidisce di UTF-16? Preferiresti se tutto fosse codificato in UTF-8? UTF-7? Oppure Che ne dici di UCS-4? Ovviamente alcune applicazioni non sono progettate per gestire il codice di un singolo carattere, ma sono necessarie, specialmente nel dominio delle informazioni globali di oggi, per la comunicazione tra i confini internazionali.
Ma in realtà, se ritieni che UTF-16 debba essere considerato dannoso perché confonde o può essere implementato in modo improprio (lunicode certamente può esserlo), quale metodo di codifica dei caratteri sarebbe considerato non dannoso?
EDIT: Per chiarire: perché considerare le implementazioni improprie di uno standard un riflesso della qualità dello standard stesso? Come altri hanno successivamente notato, semplicemente perché unapplicazione utilizza uno strumento in modo inappropriato, non significa che lo strumento è difettoso. Se così fosse, potremmo probabilmente dire cose come “var parola chiave considerata dannosa” o “threading considerato dannoso”. Penso che la domanda confonda la qualità e la natura dello standard con le difficoltà che molti programmatori incontrano nellimplementazione e usarlo correttamente, il che credo derivi più dalla loro mancanza di comprensione di come funziona lunicode, piuttosto che dallunicode stesso.
Commenti
- -1: Che ne dici di affrontare alcuni degli ' oggetti di Artyom? ons, piuttosto che limitarsi a paternalizzarlo?
- BTW: Quando ho iniziato a scrivere questo articolo volevo quasi scrivere " Larticolo di Unicode di Joel su Softeare dovrebbe essere preso in considerazione dannoso " perché ci sono molti errori. Ad esempio: la codifica utf-8 richiede fino a 4 caratteri e non 6. Inoltre non fa distinzione tra UCS-2 e UTF-16 che sono molto diversi – e in realtà causa i problemi di cui parlo.
- Inoltre, va notato che quando Joel ha scritto quellarticolo, lo standard UTF-8 ERA 6 byte, non 4. RFC 3629 ha cambiato lo standard a 4 byte diversi mesi DOPO aver scritto larticolo. Come quasi tutto su Internet, vale la pena leggere da più di una fonte ed essere consapevoli delletà delle tue fonti. Il link non era ' t intendeva essere " end all be all ", ma piuttosto un punto di partenza.
- Vorrei pic: utf-8 o utf-32 che sono: codifica a lunghezza variabile in quasi tutti i casi (incluso BMP) o codifica a lunghezza fissa sempre.
- @iconiK: non essere sciocco. UTF-16 non è assolutamente lo standard de facto per lelaborazione del testo. Mostrami un linguaggio di programmazione più adatto allelaborazione del testo che Perl, che ha sempre (beh, per più di un decennio) utilizzava caratteri astratti con una rappresentazione UTF-8 sottostante internamente. Per questo motivo, ogni programma Perl gestisce automaticamente tutti gli Unicode senza che lutente debba costantemente scervellarsi con surrogati idioti. La lunghezza di una stringa è il suo conteggio in punti di codice, non in unità di codice. Qualsiasi altra cosa è pura stupidità che mette le versioni precedenti in compatibilità con le versioni precedenti.
Risposta
Non cè niente di sbagliato in Utf- 16 codifica. Ma i linguaggi che trattano le unità a 16 bit come caratteri dovrebbero probabilmente essere considerati mal progettati. Avere un tipo denominato “char
” che non rappresenta sempre un carattere è piuttosto confuso. Poiché la maggior parte degli sviluppatori si aspetta che un tipo di carattere rappresenti un punto di codice o un carattere, molto codice probabilmente si interromperà se esposto a caratteri oltre BMP.
Nota tuttavia che anche luso di utf-32 non significa che ogni 32- Il punto di codice bit rappresenterà sempre un carattere. A causa della combinazione di caratteri, un carattere effettivo può essere costituito da più punti di codice. Unicode non è mai banale.
BTW. Probabilmente esiste la stessa classe di bug con piattaforme e applicazioni che si aspettano caratteri a 8 bit, che vengono alimentati con Utf-8.
Commenti
- Nel ' caso di Java, se guardi la loro sequenza temporale ( java.com/en/javahistory/timeline.jsp), si vede che lo sviluppo principale di String è avvenuto mentre Unicode era a 16 bit (è cambiato nel 1996). Dovevano sfruttare la capacità di gestire punti di codice non BMP, quindi la confusione.
- @Kathy: Non proprio una scusa per C #, però. In generale, sono daccordo che dovrebbe esserci un tipo
CodePoint
, contenente un singolo punto di codice (21 bit), un tipoCodeUnit
, contenente una singola unità di codice (16 bit per UTF-16) e un tipoCharacter
dovrebbero idealmente supportare un grafema completo. Ma questo lo rende funzionalmente equivalente a unString
… - Questa risposta ha quasi due anni, ma posso ' t aiuta ma commenta. " Avere un tipo chiamato ' char ' che non rappresenta sempre un carattere è carino confuso. " Eppure le persone lo usano sempre in C e simili per rappresentare dati interi che possono essere memorizzati in un singolo byte.
- E io ' ho visto un lotto di codice C che ' non gestisce correttamente la codifica dei caratteri.
- C # ha una scusa diversa: è stato progettato per Windows e Windows è stato creato su UCS-2 (' è molto fastidioso che anche oggi le API di Windows non possano supporto UTF-8). Inoltre, penso che Microsoft volesse la compatibilità Java (.NET 1.0 aveva una libreria di compatibilità Java, ma ha abbandonato il supporto Java molto rapidamente – ' immagino che ciò sia dovuto a Sun ' s querela contro MS?)
Risposta
La mia scelta personale è utilizzare sempre UTF-8. È lo standard su Linux per quasi tutto. È retrocompatibile con molte app legacy. Cè un sovraccarico minimo in termini di spazio aggiuntivo utilizzato per i caratteri non latini rispetto agli altri formati UTF e cè un notevole risparmio di spazio per i caratteri latini. Sul web, le lingue latine regnano sovrane e penso che lo faranno per il prossimo futuro. E per affrontare uno degli argomenti principali nel post originale: quasi tutti i programmatori sono consapevoli che UTF-8 a volte contiene caratteri multibyte. Non tutti lo affrontano correttamente, ma di solito sono consapevoli, il che è più di quanto si possa dire per UTF-16. Ma, ovviamente, devi scegliere quello più appropriato per la tua applicazione. Ecco perché ce nè più di uno in primo luogo.
Commenti
- UTF-16 è più semplice per qualsiasi cosa allinterno di BMP, che ' s perché è utilizzato così ampiamente. Ma anche io ' sono un fan di UTF-8, inoltre non ha problemi con lordine dei byte, il che funziona a suo vantaggio.
- Teoricamente sì. In pratica ci sono cose come, diciamo, UTF-16BE, che significa UTF-16 in big endian senza BOM. Questa non è una cosa che ho inventato, questa è una codifica effettiva consentita nei tag ID3v2.4 (i tag ID3v2 fanno schifo, ma sono, sfortunatamente, ampiamente utilizzati). E in questi casi devi definire endianness esternamente, perché il testo stesso non ' t contiene BOM. UTF-8 è sempre scritto in un modo e ' non presenta questo problema.
- No, UTF-16 non è più semplice. È più difficile. Ti inganna e ti inganna facendoti pensare che sia una larghezza fissa. Tutto questo codice è rotto e molto di più, perché non te ne accorgi finché non è troppo tardi. CASO IN POINT: ho appena trovato un altro stupido bug UTF-16 nelle librerie core Java ieri, questa volta in String.equalsIgnoreCase, che è stato lasciato nel buggery UCS-2 braindeath, e quindi fallisce su 16/17 punti di codice Unicode validi. Da quanto tempo esiste quel codice? Nessuna scusa per essere bacato. UTF-16 porta alla pura stupidità e ad un incidente in attesa di accadere. Corri urlando da UTF-16.
- @tchrist Uno deve essere uno sviluppatore molto ignorante per non sapere che UTF-16 non è di lunghezza fissa. Se inizi con Wikipedia, leggerai quanto segue allinizio: " Produce un risultato a lunghezza variabile di una o due unità di codice a 16 bit per punto di codice ". Le domande frequenti su Unicode dicono lo stesso: unicode.org/faq//utf_bom.html#utf16-1 . Non ' non so come UTF-16 possa ingannare qualcuno se è scritto ovunque che è di lunghezza variabile. Per quanto riguarda il metodo, non è mai stato progettato per UTF-16 e non dovrebbe ' essere considerato Unicode, così semplice.
- @tchrist Hai un fonte per le tue statistiche? Anche se se i bravi programmatori scarseggiano, penso che questo sia un bene, perché diventiamo più preziosi. 🙂 Per quanto riguarda le API Java, le parti basate sui caratteri potrebbero eventualmente diventare deprecate, ma questa non è una garanzia che non verranno ' utilizzate. E sicuramente non ' verranno rimossi per motivi di compatibilità.
Risposta
Bene, esiste una codifica che utilizza simboli di dimensione fissa. Intendo certamente UTF-32. Ma 4 byte per ogni simbolo sono troppo molto spazio sprecato, perché dovremmo usarlo nelle situazioni quotidiane?
A mio avviso, la maggior parte dei problemi deriva dal fatto che alcuni software sono caduti dietro lo standard Unicode, ma non sono stati rapidi nel correggere la situazione. Opera, Windows, Python, Qt: tutti sono apparsi prima che UTF-16 diventasse ampiamente conosciuto o addirittura esistesse. Posso confermare, tuttavia, che in Opera, Windows Explorer e Blocco note non ci sono più problemi con i caratteri al di fuori di BMP (almeno sul mio PC). Ma comunque, se i programmi non riconoscono le coppie surrogate, allora non usano UTF-16. Qualunque problema sorga dalla gestione di tali programmi, non hanno nulla a che fare con lo stesso UTF-16.
Tuttavia, penso che i problemi del software legacy con il solo supporto BMP siano in qualche modo esagerati. I personaggi al di fuori di BMP si incontrano solo in casi e aree molto specifiche. Secondo le FAQ ufficiali di Unicode , “anche nel testo dellAsia orientale, lincidenza delle coppie surrogate dovrebbe essere in media ben inferiore all1% di tutta la memorizzazione del testo”.Naturalmente, i caratteri al di fuori di BMP non dovrebbero essere trascurati perché altrimenti un programma non è conforme a Unicode, ma la maggior parte dei programmi non è intesa per lavorare con testi contenenti tali caratteri. Ecco perché se non lo fanno ” Non supportarlo, è spiacevole, ma non una catastrofe.
Ora consideriamo lalternativa. Se UTF-16 non esistesse, non avremmo una codifica adatta per il testo non ASCII e tutto il software creato per UCS-2 dovrebbe essere completamente riprogettato per rimanere compatibile con Unicode. Questultimo molto probabilmente rallenterebbe solo ladozione di Unicode. Inoltre non saremmo stati in grado di mantenere la compatibilità con il testo in UCS-2 come UTF-8 fa in relazione a ASCII.
Ora, mettendo da parte tutti i problemi precedenti, quali sono gli argomenti contro la codifica Dubito davvero che oggigiorno gli sviluppatori non sappiano che UTF-16 è di lunghezza variabile, è scritto ovunque a partire da Wikipedia. UTF-16 è molto meno difficile da analizzare rispetto a UTF-8, se qualcuno ha indicato la complessità come un possibile problema. Inoltre è sbagliato pensare che sia facile sbagliare determinando la lunghezza della stringa solo in UTF-16. Se usi UTF-8 o UTF-32, dovresti comunque essere consapevole che un punto di codice Unicode non significa necessariamente un carattere. A parte questo, non penso che ci sia qualcosa di sostanziale contro la codifica.
Pertanto non penso che la codifica stessa debba essere considerata dannosa. UTF-16 è un compromesso tra semplicità e compattezza e non cè nulla di male a usare ciò che è necessario dove è necessario . In alcuni casi devi rimanere compatibile con ASCII e hai bisogno di UTF-8, in alcuni casi vuoi lavorare con il lavoro con ideografi Han e risparmiare spazio usando UTF-16, in alcuni casi hai bisogno di rappresentazioni universali dei caratteri usando un -lunghezza codifica. Usa ciò che è più appropriato, fallo in modo appropriato.
Commenti
- Questo ' è una visione anglo-centrica piuttosto sbadata, Malcolm. Quasi alla pari con " ASCII è abbastanza buono per gli Stati Uniti: il resto del mondo dovrebbe adattarsi a noi ".
- In realtà ' vengo dalla Russia e incontro sempre cirillici (compresi i miei programmi), quindi non ' Non credo di avere una visione anglo-centrica. 🙂 Menzionare ASCII non è del tutto appropriato, perché ' non è Unicode e ' t supporta caratteri specifici. UTF-8, UTF-16, UTF-32 supportano gli stessi set di caratteri internazionali, sono destinati solo alluso nelle loro aree specifiche. E questo è esattamente il mio punto: se usi principalmente linglese, usa UTF-8, se usi principalmente il cirillico, usa UTF-16, se usi lingue antiche, usa UTF-32. Abbastanza semplice.
- " Non è vero, anche gli script asiatici come il giapponese, il cinese o larabo appartengono a BMP. Lo stesso BMP è in realtà molto grande e certamente abbastanza grande da includere tutti gli script usati oggi " È tutto così sbagliato. BMP contiene 0xFFFF caratteri (65536). Il cinese da solo ha più di questo. Gli standard cinesi (GB 18030) hanno più di questo. Unicode 5.1 ha già assegnato più di 100.000 caratteri.
- @Marcolm: " Lo stesso BMP è in realtà molto grande e certamente abbastanza grande da includere tutti gli script usati oggi " Non vero. A questo punto Unicode ha già assegnato circa 100.000 caratteri, molto più di quanto BMP possa ospitare. Ci sono grandi blocchi di caratteri cinesi al di fuori di BMP. E alcuni di essi sono richiesti da GB-18030 (standard cinese obbligatorio). Altri sono richiesti dagli standard giapponesi e coreani (non obbligatori). Quindi, se provi a vendere qualcosa in quei mercati, hai bisogno oltre al supporto BMP.
- Tutto ciò che utilizza UTF-16 ma può gestire solo caratteri BMP stretti non sta effettivamente utilizzando UTF-16. È bacato e rotto. La premessa dellOP è il suono: UTF-16 è dannoso, perché induce a ï cinque persone a scrivere codice non funzionante. O puoi gestire il testo Unicode, oppure no. Se non puoi, stai scegliendo un sottoinsieme, che è altrettanto stupido dellelaborazione del testo solo ASCII.
Risposta
Anni di lavoro di internazionalizzazione di Windows, in particolare nelle lingue dellAsia orientale, potrebbero avermi corrotto, ma preferisco UTF-16 per le rappresentazioni interne al programma delle stringhe e UTF-8 per larchiviazione in rete o di file di testo in chiaro. come i documenti. UTF-16 di solito può essere elaborato più velocemente su Windows, tuttavia, questo è il vantaggio principale dellutilizzo di UTF-16 in Windows.
Il passaggio a UTF-16 ha notevolmente migliorato ladeguatezza della gestione media dei prodotti testo internazionale.Ci sono solo pochi casi ristretti in cui le coppie surrogate devono essere considerate (cancellazioni, inserimenti e interruzioni di riga, fondamentalmente) e il caso medio è per lo più passante. E a differenza delle codifiche precedenti come le varianti JIS, UTF-16 limita le coppie surrogate a un intervallo molto ristretto, quindi il controllo è davvero veloce e funziona avanti e indietro.
Certo, è più o meno veloce correttamente- codificato anche UTF-8. Ma ci sono anche molte applicazioni UTF-8 non funzionanti che codificano erroneamente coppie surrogate come due sequenze UTF-8. Quindi UTF-8 non garantisce la salvezza.
IE gestisce le coppie surrogate abbastanza bene dal 2000 circa, anche se in genere le converte da pagine UTF-8 a una rappresentazione UTF-16 interna; “Sono abbastanza sicuro che anche Firefox abbia capito bene, quindi non mi interessa davvero quello che fa Opera.
UTF-32 (noto anche come UCS4) è inutile per la maggior parte delle applicazioni poiché richiede molto spazio, quindi è praticamente un non-starter.
Commenti
- Non ' abbastanza commentare le coppie UTF-8 e surrogate. Le coppie surrogate sono solo un concetto significativo nella codifica UTF-16, giusto? Forse il codice che converte direttamente dalla codifica UTF-16 alla codifica UTF-8 potrebbe sbagliare, e in questo caso, il problema è leggere in modo errato lUTF-16, non scrivere lUTF-8. È corretto?
- Ciò di cui parla Jason ' è un software che implementa deliberatamente UTF-8 in questo modo: crea una coppia surrogata, quindi UTF-8 en codificare ciascuna metà separatamente. Il nome corretto per quella codifica è CESU-8, ma Oracle (ad esempio) lo travisa come UTF-8. Java utilizza uno schema simile per la serializzazione degli oggetti, ma ' è chiaramente documentato come " UTF-8 modificato " e solo per uso interno. (Ora, se solo potessimo convincere le persone a LEGGERE quella documentazione e smettere di usare DataInputStream # readUTF () e DataOutputStream # writeUTF () in modo inappropriato …)
- AFAIK, UTF-32 è ancora codifica a lunghezza variabile, e non uguale a UCS4 che è un intervallo specifico di code point.
- @Eonil, UTF-32 sarà sempre distinguibile da UCS4 solo se abbiamo uno standard Unicode che presenta qualcosa di simile a UCS5 o superiore.
- @JasonTrue Tuttavia, solo i risultati sono uguali per coincidenza, non garantiti dal design. La stessa cosa è successa nellindirizzamento della memoria a 32 bit, Y2K, UTF16 / UCS2. O abbiamo qualche garanzia di questa uguaglianza? Se lo avessimo, lo userei volentieri. Ma non ' t voglio scrivere un codice possibile danneggiabile . Sto scrivendo un codice a livello di carattere e la mancanza di un modo garantito per transcodificare tra UTF < – > punto di codice mi sta infastidendo molto .
Risposta
UTF-8 è decisamente la strada da percorrere, possibilmente accompagnato da UTF-32 per interno utilizzare in algoritmi che richiedono un accesso casuale ad alte prestazioni (ma che ignora la combinazione di caratteri).
Sia UTF-16 che UTF-32 (così come le loro varianti LE / BE) soffrono di problemi di endianess, quindi dovrebbero non essere mai usato esternamente.
Commenti
- Laccesso casuale a tempo costante è possibile anche con UTF-8, usa solo unità di codice invece di punti di codice. Forse hai bisogno di un vero accesso al punto di codice casuale, ma ' non ho mai visto un caso duso e tu ' probabilmente vorrai accesso casuale al grapheme cluster.
Risposta
UTF-16? decisamente dannoso. Solo un pizzico di sale qui, ma ci sono esattamente tre codifiche accettabili per il testo in un programma:
- ASCII: quando si ha a che fare con cose di basso livello (ad esempio: microcontrollori) che non possono “permettersi qualcosa di meglio
- UTF8: archiviazione in supporti a larghezza fissa come file
-
punti di codice interi (“CP”?): un array degli interi più grandi che sono convenienti per il tuo linguaggio di programmazione e piattaforma (decade in ASCII nel limite delle risorse basse). Dovrebbe essere int32 sui computer più vecchi e int64 su qualsiasi cosa con indirizzamento a 64 bit.
-
Ovviamente si interfaccia con il codice legacy quale codifica è necessaria per far funzionare correttamente il vecchio codice.
Commenti
- @simon buchan, il
U+10ffff
max uscirà dalla finestra quando (non se) esauriscono i punti di codice. Detto questo, luso di int32 su un sistema p64 per la velocità è probabilmente sicuro, poiché dubito che ' supereràU+ffffffff
prima di te è stato costretto a riscrivere il codice per sistemi a 128 bit intorno al 2050. (Questo è il punto in cui " usa il più grande int che è conveniente " anziché " più grande disponibile " (che probabilmente sarebbe int256 o bignums o qualcosa del genere). - @David: Unicode 5.2 codifica 107.361 punti di codice.Ci sono 867.169 codepoint non utilizzati. " quando " è semplicemente stupido. Un punto di codice Unicode è definito come un numero compreso tra 0 e 0x10FFFF, una proprietà da cui dipende UTF-16. (Anche il 2050 sembra una stima molto bassa per i sistemi a 128 bit quando un sistema a 64 bit può contenere lintera Internet nello spazio degli indirizzi '.)
- @David: Il tuo " quando " si riferiva allesaurimento dei codepoint Unicode, non a un interruttore a 128 bit che, sì, sarà nei prossimi secoli. A differenza della memoria, non vi è crescita esponenziale dei caratteri, quindi Unicode Consortium ha specificamente garantito che non assegnerà mai un punto di codice sopra
U+10FFFF
. Questa è davvero una di quelle situazioni in cui 21 bit sono sufficienti per chiunque. - @Simon Buchan: Almeno fino al primo contatto. 🙂
- Unicode utilizzato per garantire che non ci siano punti di codice sopra U + FFFF.
Risposta
Unicode definisce punti di codice fino a 0x10FFFF (1.114.112 codici), tutte le applicazioni in esecuzione in ambiente multilingue con stringhe / nomi di file ecc. dovrebbe gestirlo correttamente.
Utf-16 : copre solo 1.112.064 codici. Anche se quelli alla fine di Unicode provengono dagli aerei 15-16 (Area ad uso privato). Non può crescere ulteriormente in futuro se non rompendo il concetto Utf-16 .
Utf-8 : copre teoricamente 2.216.757.376 codici. Lattuale intervallo di codici Unicode può essere rappresentato da una sequenza di massimo 4 byte. Non soffre di problemi con byte order , è “compatibile” con ascii.
Utf-32 : copre teoricamente 2 ^ 32 = 4.294.967.296 codici. Attualmente non è codificato a lunghezza variabile e probabilmente non lo sarà in futuro.
Questi fatti sono autoesplicativi. Non capisco la necessità di un uso generale di Utf-16 . È codificato a lunghezza variabile (non è possibile accedervi dallindice), ha problemi a coprire lintero intervallo Unicode anche al momento, lordine dei byte deve essere gestito, ecc. Non vedo alcun vantaggio tranne che viene utilizzato in modo nativo in Windows e in altri luoghi. Anche se durante la scrittura di codice multipiattaforma è probabilmente meglio utilizzare Utf-8 in modo nativo ed effettuare conversioni solo ai punti finali in modo dipendente dalla piattaforma (come già suggerito). Quando è necessario laccesso diretto tramite indice e la memoria non è un problema, è necessario utilizzare Utf-32 .
Il problema principale è che molti programmatori che si occupano di Windows Unicode = Utf-16 non sanno o ignorano nemmeno il fatto che è codificato a lunghezza variabile.
Il modo in cui di solito è nella piattaforma * nix è abbastanza buono, stringhe c (char *) interpretate come Utf-8 codificate, stringhe c larghe (wchar_t *) interpretate come Utf-32 .
Commenti
- Nota: UTF -16 copre All Unicode poiché Unicode Consortium ha deciso che 10FFFF è lintervallo TOP di Unicode e ha definito UTF-8 lunghezza massima di 4 byte e intervallo escluso esplicitamente 0xD800-0xDFFF dallintervallo di punti di codice valido e questo intervallo viene utilizzato per la creazione del surrogato coppie. Quindi qualsiasi testo Unicode valido può essere rappresentato con ciascuna di queste codifiche. Anche sulla crescita verso il futuro. Non ' sembra che 1 milione di punti di codice non sarebbe sufficiente in un lontano futuro.
- @Kerrek: Errato: UCS-2 non è un Unicode valido codifica. Tutte le codifiche UTF- * per definizione possono rappresentare qualsiasi punto di codice Unicode legale per linterscambio. UCS-2 può rappresentare molto meno di quello, più alcuni in più. Ripeto: UCS-2 non è una codifica Unicode valida, qualsiasi più di ASCII lo è.
- " Non capisco che sostenga luso generale di Utf- 8 . È codificato a lunghezza variabile (non è possibile accedervi dallindice) "
- @Ian Boyd, la necessità di accedere al carattere individuale di una stringa in uno schema di accesso casuale è incredibilmente sopravvalutato. È comune quanto voler calcolare la diagonale di una matrice di caratteri, il che è molto raro. Le stringhe vengono praticamente sempre elaborate in sequenza, e poiché laccesso a UTF-8 char N + 1 dato che sei a UTF-8 char N è O (1), non ci sono problemi. Non cè bisogno di fare un accesso casuale alle stringhe. Se pensi che valga la pena di utilizzare lo spazio di archiviazione per utilizzare UTF-32 invece che UTF-8 è la tua opinione, ma per me è del tutto un non problema.
- @tchrist, lo concedo le tue stringhe vengono praticamente sempre elaborate in modo sequenziale se includi literazione inversa come " sequenziale " e allunghi un po più il confronto dellestremità finale di una stringa a una stringa nota. Due scenari molto comuni sono il troncamento degli spazi alla fine delle stringhe e il controllo dellestensione del file alla fine di un percorso.
Risposta
Aggiungilo alla lista:
Lo scenario presentato è semplice (anche più semplice visto che lo presenterò qui di quanto non fosse originariamente! ): 1. Un WinForms TextBox si trova su un form, vuoto. Ha un MaxLength impostato su 20 .
2.Lutente digita nel TextBox, o forse incolla il testo al suo interno.
3.Non importa cosa digiti o incolli nella casella di testo, sei limitato a 20, anche se emetterà un segnale acustico per simpatia al testo oltre il 20 (YMMV qui; ho cambiato il mio schema sonoro per darmi quelleffetto!).
4. Il piccolo pacchetto di testo viene quindi inviato da qualche altra parte, per iniziare unavventura emozionante.
Questo è uno scenario facile e chiunque può scriverlo nel tempo libero. Lho scritto da solo in più linguaggi di programmazione usando WinForms, perché ero annoiato e non lavevo mai provato prima. E con il testo in più lingue reali perché sono cablato in quel modo e ho più layout di tastiera di chiunque altro nellintero fottuto universo.
Ho persino chiamato il modulo Magic Carpet Ride , per alleviare la noia.
Non ha funzionato, per quello che vale.
Quindi, invece, ho inserito il seguente 20 caratteri nel mio Magic Carpet Ride modulo:
0123401234012340123 𠀀
Uh oh.
Lultimo carattere è U + 20000, il primo Estensione B ideogramma di Unicode (aka U + d840 U + dc00, ai suoi amici intimi che non si vergogna di essere spogliato, per così dire, di fronte) ….
E ora abbiamo un gioco con la palla.
Perché quando TextBox. MaxLength parla di
Ottiene o imposta il numero massimo di caratteri che possono essere inseriti manualmente nella casella di testo.
ciò che realmente significa è
Ottiene o imposta il numero massimo di UTF-16 LE cod Le unità che possono essere inserite manualmente nella casella di testo e tronceranno senza pietà la merda vivente da qualsiasi stringa che cerchi di giocare a giochi simpatici con la nozione di carattere linguistico che solo qualcuno ossessionato come quel tipo di Kaplan troverà offensivo (accidenti, deve farlo uscire di più!).
Proverò a vedere come aggiornare il documento ….
Lettori abituali che ricorda che la mia serie da UCS-2 a UTF-16 noterà la mia infelicità con la nozione semplicistica di TextBox.MaxLength e come dovrebbe gestire come minimo questo caso in cui il suo comportamento draconiano crea una sequenza illegale, una che altre parti di .Net Framework potrebbero lanciare un
- System.Text.EncoderFallbackException : Impossibile tradurre il carattere Unicode \ uD850 allindice 0 nella codepage specificata. *
eccezione se si passa questa stringa altrove in .Net Framework (come stava facendo il mio collega Dan Thompson).
Ora ok, forse lintera serie da UCS-2 a UTF-16 è fuori dalla portata di molti.
Ma non lo è “È ragionevole aspettarsi che TextBox.Text non produca un System.String che” non causa il lancio di un altro pezzo di .Net Framework? Voglio dire, non è che ci sia una possibilità sotto forma di qualche evento sul controllo che ti dice del troncamento imminente in cui puoi facilmente aggiungere la convalida più intelligente – convalida che il controllo stesso non si preoccupa di fare. arrivare al punto di dire che questo controllo punk sta infrangendo un contratto di sicurezza che potrebbe persino portare a problemi di sicurezza se puoi classificare che causano eccezioni impreviste per terminare unapplicazione come una sorta di rozza negazione del servizio. lalgoritmo o la tecnica producono risultati non validi?
Fonte: Michael S.Blog Kaplan MSDN
Commenti
- Grazie, ottimo collegamento! Lho ' lho aggiunto allelenco dei problemi nella domanda.
Risposta
Non direi necessariamente che UTF-16 è dannoso. Non è elegante, ma serve allo scopo della retrocompatibilità con UCS-2, proprio come GB18030 fa con GB2312 e UTF-8 fa con ASCII.
Ma apportare una modifica fondamentale alla struttura di Unicode nel midstream, dopo che Microsoft e Sun avevano costruito enormi API intorno a caratteri a 16 bit, era dannoso. Limpossibilità di diffondere la consapevolezza del cambiamento è stata più dannosa.
Commenti
- UTF-8 è un superset di ASCII , ma UTF-16 NON è un superset di UCS-2. Sebbene quasi un superset, una corretta codifica di UCS-2 in UTF-8 risulta nellabominio noto come CESU-8; UCS-2 non ' ha surrogati, solo punti di codice ordinari, quindi devono essere tradotti come tali. Il vero vantaggio di UTF-16 è che ' è più facile aggiornare una base di codice UCS-2 rispetto a una riscrittura completa per UTF-8. Divertente, eh?
- Certo, tecnicamente UTF-16 non è ' un superset di UCS-2, ma quando mai sono stati U + D800 a U + DFFF utilizzato per qualsiasi cosa eccetto per i surrogati UTF-16?
- ' non importa. Qualsiasi elaborazione diversa dal passaggio alla cieca attraverso il bytestream richiede la decodifica delle coppie surrogate, cosa che ' non puoi eseguire se ' stai trattando come UCS-2.
Risposta
UTF-16 è il miglior compromesso tra gestione e spazio ed è per questo che la maggior parte delle piattaforme principali (Win32, Java, .NET) lo utilizza per la rappresentazione interna delle stringhe.
Commenti
- -1 perché UTF-8 è probabilmente più piccolo o non significativamente diverso. Per alcuni script asiatici UTF-8 è tre byte per glifo mentre UTF-16 è solo due, ma questo è bilanciato dal fatto che UTF-8 è solo un byte per ASCII (che spesso appare anche allinterno delle lingue asiatiche nei nomi dei prodotti, nei comandi e cose simili). Inoltre, in tali lingue, un glifo trasmette più informazioni di un carattere latino quindi è giustificato per occupare più spazio.
- Non chiamerei la combinazione del wor I lati di entrambe le opzioni un buon compromesso.
- ' non è più facile di UTF-8. ' è anche a lunghezza variabile.
- Lasciando da parte i dibattiti sui vantaggi di UTF-16: ciò che hai citato non è motivo per Windows, Java o .NET utilizzando UTF-16. Windows e Java risalgono a unepoca in cui Unicode era una codifica a 16 bit. LUCS-2 era una scelta ragionevole allepoca. Quando Unicode è diventato una codifica a 21 bit, la migrazione a UTF-16 è stata la scelta migliore per le piattaforme esistenti. Ciò non aveva nulla a che fare con la facilità di utilizzo o i compromessi di spazio. ' è solo una questione di eredità.
- .NET eredita leredità di Windows qui.
Risposta
Non ho mai capito il punto di UTF-16. Se vuoi la rappresentazione più efficiente in termini di spazio, usa UTF-8. Se vuoi essere in grado di tratta il testo come di lunghezza fissa, usa UTF-32. Se non vuoi nessuno dei due, usa UTF-16. Peggio ancora, poiché tutti i caratteri comuni (piano multilingue di base) in UTF-16 rientrano in un unico punto di codice, bug che presumono che UTF-16 è di lunghezza fissa sarà sottile e difficile da trovare, mentre se provi a farlo con UTF-8, il tuo codice fallirà velocemente e rumorosamente non appena proverai a internazionalizzare.
Risposta
Dato che non posso ancora commentare, lo posto come risposta, poiché sembra che non possa altrimenti contattare gli autori di utf8everywhere.org
. È un peccato che non ottenga automaticamente il privilegio di commento, dato che ho abbastanza reputazione su altri scambi di stack.
Questo è da intendersi come un commento alla Opinione: Sì, UTF-16 dovrebbe essere considerato dannoso risposta.
Una piccola correzione:
Per evitare che uno passi accidentalmente un UTF-8 char*
nelle versioni con stringa ANSI delle funzioni API di Windows, si dovrebbe definire UNICODE
, non _UNICODE
. _UNICODE
mappa funzioni come _tcslen
con wcslen
, non MessageBox
a MessageBoxW
. Invece, la definizione UNICODE
si occupa di questultima. A titolo di prova, questo proviene dallintestazione WinUser.h
di MS Visual Studio 2005:
#ifdef UNICODE #define MessageBox MessageBoxW #else #define MessageBox MessageBoxA #endif // !UNICODE
Come minimo, questo errore dovrebbe essere corretto su utf8everywhere.org
.
Un suggerimento:
Forse la guida dovrebbe contenere un esempio di uso esplicito del Wide- versione stringa di una struttura dati, per renderla meno facile perderla / dimenticarla.Lutilizzo di versioni a stringa larga delle strutture dati in aggiunta allutilizzo di versioni a stringa larga delle funzioni rende ancora meno probabile che si chiami accidentalmente una versione stringa ANSI di tale funzione.
Esempio dellesempio:
WIN32_FIND_DATAW data; // Note the W at the end. HANDLE hSearch = FindFirstFileW(widen("*.txt").c_str(), &data); if (hSearch != INVALID_HANDLE_VALUE) { FindClose(hSearch); MessageBoxW(nullptr, data.cFileName, nullptr, MB_OK); }
Commenti
- Concordato; Grazie! Aggiorneremo il documento. Il documento necessita ancora di ulteriore sviluppo e aggiunta di informazioni sui database. Siamo felici di ricevere contributi di parole.
- @PavelRadzivilovsky
_UNICODE
è ancora lì 🙁 - grazie per avermelo ricordato. Cubus, Jelle, Vorresti un utente per il nostro SVN?
- @Pavel Certo, lo apprezzerei!
- @JelleGeerts: Mi scuso per questo ritardo. Puoi sempre contattarci tramite le nostre email (link dal manifesto) o Facebook. Siamo facili da trovare. Anche se credo che abbiamo risolto il problema che hai portato qui (e ti ho accreditato lì), lintero dibattito UTF-8 vs UTF-16 è ancora rilevante. Se hai altro da fare contribuisci non esitare a contattarci tramite questi canali privati.
Rispondi
Qualcuno ha detto che UCS4 e UTF-32 erano Lo stesso. No, ma so cosa intendi. Uno di loro è una codifica dellaltro, però. Vorrei che avessero pensato di specificare endianness dal primo in modo da non avere la battaglia endianess combattuta anche qui. Non potevano averlo visto arrivare? Almeno UTF-8 è lo stesso ovunque re (a meno che qualcuno non stia seguendo la specifica originale con 6 byte).
Se usi UTF-16, devi includere la gestione dei caratteri multibyte. Non puoi andare allennesimo carattere indicizzando 2N in un array di byte. Devi percorrerlo o avere indici di caratteri. Altrimenti hai scritto un bug.
Lattuale bozza delle specifiche di C ++ dice che UTF-32 e UTF-16 possono avere varianti little-endian, big-endian e non specificate. Veramente? Se Unicode avesse specificato che tutti dovevano fare little endian dallinizio, sarebbe stato tutto più semplice. (Sarei andato bene anche con il big-endian.) Invece, alcune persone lo hanno implementato in un modo, altri nellaltro, e ora siamo bloccati con stupidità per niente. A volte è imbarazzante essere un ingegnere del software.
Commenti
- Lendianess non specificato dovrebbe includere BOM come primo carattere, utilizzato per determinare in che modo deve essere letta la stringa. UCS-4 e UTF-32 sono effettivamente gli stessi oggigiorno, ovvero un valore UCS numerico compreso tra 0 e 0x10FFFF memorizzato in un numero intero a 32 bit.
- @Tronic: Tecnicamente, questo non è vero. Sebbene UCS-4 possa memorizzare qualsiasi numero intero a 32 bit, a UTF-32 è vietato memorizzare i punti di codice non di carattere che sono illegali per linterscambio, come 0xFFFF, 0xFFFE e tutti i surrogati. UTF è una codifica di trasporto, non interna.
- I problemi di endianness sono inevitabili fintanto che processori diversi continuano a utilizzare ordini di byte diversi. Tuttavia, sarebbe stato utile se ci fosse un " preferito " ordine di byte per larchiviazione di file di UTF-16.
- Anche se UTF-32 è a larghezza fissa per i punti di codice , non è a larghezza fissa per i caratteri . (Hai sentito parlare di qualcosa chiamato " che combina caratteri "?) Quindi puoi ' andare al N ' esimo carattere semplicemente indicizzando 4N nellarray di byte.
Risposta
Non penso che sia dannoso se lo sviluppatore è abbastanza attento.
E dovrebbero accettare questo compromesso se anche loro lo sanno bene.
Come sviluppatore di software giapponese, trovo UCS-2 abbastanza grande e limitare lo spazio apparentemente semplifica la logica e riduce la memoria di runtime, quindi usare utf-16 sotto la limitazione UCS-2 è abbastanza buono.
Ci sono filesystem o altre applicazioni che presumono che codepoint e byte siano proporzionali, in modo che il numero di codepoint grezzo possa essere garantito per adattarsi a una memoria di dimensioni fisse.
Un esempio è NTFS e VFAT che specificano UCS-2 come codifica di archiviazione del nome file.
Se questo esempio vuole davvero estendersi per supportare UCS-4, potrei comunque essere daccordo nellusare utf-8 per tutto, ma la lunghezza fissa ha buoni punti come:
- garantire la dimensione in base alla lunghezza (la dimensione dei dati e la lunghezza del punto di codice sono proporzionali)
- può usare il numero di codifica per la ricerca hash
- i dati non compressi sono di dimensioni ragionevoli (rispetto a utf-32 / UCS-4)
In futuro, quando la memoria / potenza di elaborazione sarà a buon mercato anche in qualsiasi dispositivo incorporato, potremmo accettare che il dispositivo sia un po lento per mancanza di cache extra o errori di pagina e memoria extra utilizzo, ma questo non accadrà nel prossimo futuro immagino …
Commenti
- Per coloro che leggono questo commento, vale la pena notare che UCS- 2 non è la stessa cosa di UTF-16. Si prega di cercare le differenze per capire.
Risposta
“Uno dei più popolari le codifiche UTF-16 possono essere considerate dannose? “
Molto probabilmente, ma le alternative non dovrebbero essere necessariamente viste come molto migliori.
La questione fondamentale è che ci sono molti concetti diversi su: glifi, caratteri, punti di codice e sequenze di byte. La mappatura tra ognuno di questi non è banale, anche con lausilio di una libreria di normalizzazione. (Ad esempio, alcuni caratteri nelle lingue europee che sono scritti con una scrittura latina non sono scritti con un singolo punto di codice Unicode. E questo è allestremità più semplice della complessità!) Ciò significa che per ottenere tutto corretto è abbastanza sorprendentemente difficile; ci si possono aspettare bizzarri bug (e invece di lamentarsene qui, dì ai manutentori del software in questione).
Lunico modo in cui UTF- 16 può essere considerato dannoso rispetto, ad esempio, UTF-8 è che ha un modo diverso di codificare i punti di codice al di fuori del BMP (come coppia di surrogati). Se il codice desidera accedere o iterare per punto di codice, ciò significa che deve essere consapevole della differenza. OTOH, significa che un corpo sostanziale di codice esistente che assume “caratteri” può sempre essere contenuto in una quantità di due byte – unipotesi abbastanza comune, anche se sbagliata – può almeno continua a lavorare senza ricostruire tutto. In altre parole, almeno puoi vedere quei personaggi che non vengono gestite correttamente!
Capovolgerei la tua domanda e direi che lintera dannata faccenda di Unicode dovrebbe essere considerata dannosa e tutti dovrebbero usare una codifica a 8 bit, tranne Ho visto (negli ultimi 20 anni) dove questo porta: orribile confusione sulle varie codifiche ISO 8859, più lintero set di quelle usate per il cirillico e la suite EBCDIC, e … beh, Unicode per tutti i suoi difetti batte quella . Se solo non fosse “t un così brutto compromesso tra diversi paesi” incomprensioni.
Commenti
- Conoscendo la nostra fortuna, in pochi anni ' ci ritroveremo a corto di spazio in UTF-16. Meh.
- La questione fondamentale è che il testo è ingannevolmente difficile. Nessun approccio alla rappresentazione di tali informazioni in modo digitale può essere semplice. È ' è lo stesso motivo per cui le date sono difficili, i calendari sono difficili, il tempo è difficile, i nomi personali sono difficili, gli indirizzi postali sono difficili: ogni volta che le macchine digitali si intersecano con i costrutti culturali umani, la complessità erutta. È un dato di fatto. Gli esseri umani non funzionano sulla logica digitale.