Commentaires
- Pas vraiment correct. Jexplique, si vous écrivez " שָׁ " le caractère composé qui se compose de " ש ", " ָ " et " ׁ ", vovels, alors la suppression de chacun deux est logique, vous supprimez un point de code lorsque vous appuyez sur " retour arrière " et supprimez tous les caractères, y compris les vovels, lorsque vous appuyez sur " del ". Mais vous ne produisez jamais d’état de texte illégal – des points de code illégaux. Ainsi, la situation lorsque vous appuyez sur retour arrière et obtenez du texte illégal est incorrecte.
- CiscoIPPhone: Si un bogue est " signalé plusieurs fois, par de nombreuses personnes différentes ", puis quelques années plus tard, un développeur écrit sur un blog de développement que " Croyez-le ou non, le comportement est principalement intentionnel! ", alors (pour le dire légèrement) jai tendance à penser que ' nest probablement pas la meilleure décision de conception jamais prise. 🙂 Simplement parce que ' est intentionnel ' que cela signifie ' nest pas un bug.
- Excellent message. UTF-16 est en effet le " pire des deux mondes ": UTF8 est de longueur variable, couvre tout lUnicode, nécessite un algorithme de transformation vers et depuis les points de code bruts, se limite à lASCII, et il na aucun problème dendianness. UTF32 est de longueur fixe, ne nécessite aucune transformation, mais prend plus despace et présente des problèmes dendianité. Jusquici tout va bien, vous pouvez utiliser UTF32 en interne et UTF8 pour la sérialisation. Mais UTF16 na aucun avantage: il ' dépend de lendian, il est ' de longueur variable, il prend beaucoup despace, il ' nest pas compatible ASCII. Leffort nécessaire pour gérer correctement UTF16 pourrait être mieux dépensé sur UTF8.
- @Ian: UTF-8 NA PAS les mêmes mises en garde que UTF-8. Vous ne pouvez pas avoir de substituts en UTF-8. UTF-8 ne se fait pas passer pour quelque chose d’autre, mais la plupart des programmeurs utilisant l’UTF-16 l’utilisent mal. Je sais. Je ' les ai regardés encore et encore et encore et encore.
- De plus, UTF-8 ne ' t ont le problème car tout le monde le traite comme un encodage à largeur variable. La raison pour laquelle UTF-16 a le problème est que tout le monde le traite comme un encodage à largeur fixe.
Réponse
Ceci est une ancienne réponse.
Voir UTF-8 Everywhere pour les dernières mises à jour.
Opinion: Oui, lUTF-16 doit être considéré comme dangereux . La raison même pour laquelle il existe est quil y a quelque temps, il y avait une croyance erronée que widechar allait être ce que UCS-4 est maintenant.
Malgré l « anglo-centrisme » de lUTF-8, il devrait être considéré comme le seul encodage utile pour le texte. On peut affirmer que les codes sources des programmes, des pages Web et des fichiers XML, les noms de fichiers du système dexploitation et dautres interfaces texte dordinateur à ordinateur nauraient jamais dû exister. Mais quand ils le font, le texte nest pas seulement destiné aux lecteurs humains.
Dun autre côté, les frais généraux UTF-8 sont un petit prix à payer tout en présentant des avantages significatifs. Des avantages tels que la compatibilité avec du code inconscient qui transmet simplement des chaînes avec char*
. Cest une bonne chose. Il « y a peu de caractères utiles qui sont PLUS COURTS en UTF-16 quils ne le sont en UTF-8.
Je crois que tous les autres encodages finiront par mourir. Cela implique que MS-Windows, Java, ICU, python cessez de lutiliser comme favori. Après de longues recherches et discussions, les conventions de développement de mon entreprise interdisent dutiliser UTF-16 partout sauf les appels dAPI du système dexploitation, et ce malgré limportance des performances de nos applications et du fait que nous utilisons Windows. Les fonctions de conversion ont été développées pour convertir les std::string
s en UTF-16 natif, que Windows lui-même ne prend pas en charge correctement .
Aux gens qui disent « utilisez ce dont vous avez besoin là où cest nécessaire « , je dis: il « y a un énorme avantage à utiliser le même encodage partout, et je ne vois aucune raison suffisante pour faire autrement. En particulier, je pense que lajout de wchar_t
à C ++ était une erreur, tout comme les ajouts Unicode à C ++ 0x. Ce qui doit être exigé des implémentations STL, cest que chaque Le paramètre std::string
ou char*
serait considéré comme compatible Unicode.
Je suis également contre lutilisation de « ce que vous voulez « approche. Je ne vois aucune raison pour une telle liberté. Il y a assez de confusion sur le sujet du texte, ce qui entraîne tout ce logiciel cassé. Cela dit, je suis convaincu que les programmeurs doivent enfin parvenir à un consensus sur UTF-8 comme un moyen approprié. (Je viens dun pays qui ne parle pas ascii et jai grandi sous Windows, donc je serais censé attaquer pour la dernière fois UTF-16 pour des raisons religieuses).
Jaimerais partager plus dinformations sur la façon dont je fais du texte sur Windows, et ce que je recommande à tout le monde pour lexactitude unicode vérifiée au moment de la compilation, la facilité dutilisation et une meilleure multi-plateforme du code. La suggestion diffère considérablement de ce qui est généralement recommandé comme moyen approprié dutiliser Unicode sur Windows. Pourtant, une recherche approfondie de ces recommandations a abouti à la même conclusion. Alors voici:
- Nutilisez pas
wchar_t
oustd::wstring
à un endroit autre que le point adjacent à API acceptant UTF-16. - Nutilisez pas
_T("")
ouL""
littéraux UTF-16 (ceux-ci devraient être retirés de la norme IMO , dans le cadre de la dépréciation UTF-16). - Nutilisez pas de types, de fonctions ou de leurs dérivés sensibles à la constante
_UNICODE
, tels queLPTSTR
ouCreateWindow()
. - Pourtant,
_UNICODE
toujours défini, pour évitez de transmettre des chaîneschar*
à WinAPI pour obtenir une compilation silencieuse -
std::strings
etchar*
nimporte où dans le programme sont considérés comme UTF-8 (sauf indication contraire) - Toutes mes chaînes sont
std::string
, bien que vous puissiez passer char * ou string literal àconvert(const std::string &)
. -
utilisez uniquement les fonctions Win32 qui acceptent les widechars (
LPWSTR
). Jamais ceux qui acceptentLPTSTR
ouLPSTR
. Passez les paramètres de cette façon:::SetWindowTextW(Utils::convert(someStdString or "string litteral").c_str())
(La politique utilise les fonctions de conversion ci-dessous.)
-
Avec des chaînes 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);
-
Utilisation de fichiers, noms de fichiers et fstream sous Windows:
- Ne passez jamais
std::string
ouconst char*
arguments de nom de fichier pour la famillefstream
. MSVC STL ne prend pas en charge les arguments UTF-8, mais possède une extension non standard qui doit être utilisée comme suit: -
Convertit les arguments
std::string
enstd::wstring
avecUtils::Convert
:std::ifstream ifs(Utils::Convert("hello"), std::ios_base::in | std::ios_base::binary);
Nous « devrons » manuellement supprimer le converti, lorsque lattitude de MSVC envers
fstream
change. - Ce code nest pas multi-plateforme et devra peut-être être modifié manuellement dans le futur
- Voir
fstream
cas de recherche / discussion unicode 4215 pour plus dinformations. - Ne produisez jamais de fichiers de sortie texte avec un contenu non UTF8
- Évitez dutiliser
fopen()
pour des raisons RAII / OOD. Si nécessaire, utilisez_wfopen()
et les conventions WinAPI ci-dessus.
- Ne passez jamais
// 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 }
Commentaires
- Je ne peux ' être daccord. Les avantages de utf16 par rapport à utf8 pour de nombreuses langues asiatiques dominent complètement les arguments que vous faites. Il est naïf despérer que les Japonais, Thaïlandais, Chinois, etc. abandonneront cet encodage. Les conflits problématiques entre les jeux de caractères surviennent lorsque les jeux de caractères semblent pour la plupart similaires, sauf avec des différences. Je suggère de normaliser sur: fixe 7 bits: iso-irv-170; Variable 8 bits: utf8; Variable 16 bits: utf16; 32bit fixe: ucs4.
- @Charles: merci pour votre contribution. Certes, certains caractères BMP sont plus longs en UTF-8 quen UTF-16. Mais voyons les choses en face de ': le problème nest pas en octets que prennent les caractères chinois BMP, mais la complexité de conception logicielle qui en découle. Si un programmeur chinois doit de toute façon concevoir des caractères de longueur variable, il semble que lUTF-8 soit toujours un petit prix à payer par rapport aux autres variables du système. Il pourrait utiliser UTF-16 comme algorithme de compression si lespace est si important, mais même dans ce cas, il ne correspondra pas à LZ, et après LZ ou une autre compression générique, les deux prennent à peu près la même taille et la même entropie. Ce que je dis fondamentalement, cest que la simplification offerte par un encodage One qui est également compatible avec les programmes char * existants, et qui est également le plus populaire aujourdhui pour tout, est inimaginable.Cest presque comme au bon vieux temps " texte en clair ". Vous voulez ouvrir un fichier avec un nom? Inutile de se soucier du type dUnicode que vous utilisez, etc. Je suggère à nous, développeurs, de limiter UTF-16 à des cas très particuliers doptimisation sévère où un tout petit peu de performance vaut des mois-homme de travail.
- Linux a eu une exigence spécifique lors du choix dutiliser UTF-8 en interne: la compatibilité avec Unix. Windows n’avait ' pas besoin de cela, et donc, lorsque les développeurs ont implémenté Unicode, ils ont ajouté des versions UCS-2 de presque toutes les fonctions traitant du texte et ont simplement converti les fonctions multioctets en UCS-2 et appelez les autres. Ils remplacent plus tard UCS-2 par UTF-16. Linux dautre part a conservé les encodages 8 bits et a donc utilisé UTF-8, car ' est le bon choix dans ce cas.
- @Pavel Radzivilovsky : BTW, vos écrits sur " Je crois que tous les autres encodages finiront par mourir. Cela implique que MS-Windows, Java, ICU et python cessent de lutiliser comme favori. " et " En particulier, je pense que lajout de wchar_t à C ++ était une erreur, tout comme les ajouts Unicode à C ++ Ox. " sont soit assez naïfs, soit très très arrogants . Et cela vient de quelquun qui code à la maison avec un Linux et qui est satisfait des caractères UTF-8. Pour dire les choses franchement: Cela na ' pas se produire .
Réponse
Les points de code Unicode ne sont pas des caractères! Parfois, ce ne sont même pas des glyphes (formes visuelles) .
Quelques exemples:
- Points de code en chiffres romains comme « ⅲ ». (Un caractère unique qui ressemble à « iii ».)
- Caractères accentués comme « á », qui peuvent être représentés soit comme un seul caractère combiné « \ u00e1 » ou comme un caractère et diacritique séparé « \ u0061 \ u0301 « .
- Caractères comme le grec minuscule sigma, qui ont des formes différentes pour le milieu ( » σ « ) et la fin ( » ς « ) des positions des mots, mais qui devraient être considérés comme des synonymes de recherche.
- Tiret discrétionnaire Unicode U + 00AD, qui peut ou non être affiché visuellement, selon le contexte, et qui est ignoré pour la recherche sémantique.
Les seuls moyens dobtenir lédition Unicode le droit est de utiliser une bibliothèque écrite par un expert , ou devenir un expert et en écrire une vous-même. Si vous ne comptez que des points de code, vous vivez dans un état de péché.
Commentaires
- Ceci. Beaucoup cela. UTF-16 peut causer des problèmes, mais même utiliser UTF-32 partout peut (et va) toujours vous donner des problèmes.
- Quest-ce quun personnage? Vous pouvez définir un point de code comme un caractère et vous en tirer très bien. Si vous voulez dire un glyphe visible par lutilisateur, cest autre chose.
- @tchrist est sûr que pour allouer de lespace, cette définition convient, mais pour autre chose? Pas tellement. Si vous gérez un caractère de combinaison comme un caractère unique (par exemple pour une opération de suppression ou " prenez les N premiers caractères "), vous ' Jaurai un comportement étrange et erroné. Si un point de code na de sens que lorsquil est combiné avec au moins un autre, vous pouvez ' le gérer seul de manière sensée.
- @Pacerier, cest tard à la fête, mais je dois commenter cela. Certaines langues ont de très grands ensembles de combinaisons potentielles de signes diacritiques (c.f. vietnamien, cest-à-dire mệt đừ). Avoir des combinaisons plutôt quun caractère par diacritique est très utile.
- une petite note sur la terminologie: les points de code font correspondent aux caractères unicode ; ce dont Daniel parle ici, ce sont les caractères perçus par lutilisateur , qui correspondent aux clusters de graphèmes unicode
Answer
Il existe une règle empirique simple sur le formulaire de transformation Unicode (UTF) à utiliser: – utf-8 pour le stockage et la communication – utf-16 pour le traitement des données – vous pourriez aller avec utf-32 si la plupart de lAPI de plate-forme que vous utilisez est utf-32 (commun dans le monde UNIX).
La plupart des systèmes utilisent aujourdhui utf-16 (Windows, Mac OS, Java, .NET, ICU , Qt). Voir également ce document: http://unicode.org/notes/tn12/
Retour à « UTF-16 comme dangereux », Je dirais: certainement pas.
Les gens qui ont peur des substituts (pensant quils transforment Unicode en un encodage à longueur variable) ne comprennent pas les autres complexités (bien plus importantes) qui rendent le mappage entre les caractères et un point de code Unicode très complexe: combinaison de caractères, ligatures, sélecteurs de variation, caractères de contrôle, etc.
Il suffit de lire cette série ici http://www.siao2.com/2009/06/29/9800913.aspx et voyez comment lUTF-16 devient un problème facile.
Commentaires
- Veuillez ajouter quelques exemples où UTF-32 est courant dans le monde UNIX!
- Non, vous ne le faites pas souhaitez utiliser UTF-16 pour le traitement des données. Cest ' que cest une douleur dans le cul. Il présente tous les inconvénients de lUTF-8 mais aucun de ses avantages. UTF-8 et UTF-32 sont clairement supérieurs au piratage vicieux précédemment connu sous le nom de Mme UTF-16, dont le nom de jeune fille était UCS-2.
- Hier, je viens de trouver un bogue dans la classe Java Core String.
equalsIgnoreCase
méthode (également dautres dans la classe string) qui naurait jamais été là si Java avait utilisé UTF-8 ou UTF-32. Il y a des millions de ces bombes endormies dans nimporte quel code qui utilise UTF-16, et jen ai assez. UTF-16 est une pox vicieuse qui infeste notre logiciel de bogues insidieux pour toujours et à jamais. Il est clairement dangereux, et devrait être obsolète et banni. - @tchrist Wow, donc une fonction non compatible avec les substituts (car elle a été écrite alors quil ny en avait pas et est malheureusement documentée de telle manière quelle est probablement impossible à adapter – il spécifie .toUpperCase (char)) entraînera un mauvais comportement? Vous ' savez quune fonction UTF-32 avec une carte de points de code obsolète ne ' pas gérer cela mieux? De plus, toute lAPI Java ne gère pas particulièrement bien les substituts et les points les plus complexes sur Unicode pas du tout – et avec le dernier codage utilisé naurait ' aucune importance.
- -1: Un
.Substring(1)
inconditionnel dans .NET est un exemple trivial de quelque chose qui rompt la prise en charge de tous les Unicode non BMP. Tout qui utilise UTF-16 a ce problème; il ' est trop facile de le traiter comme un encodage à largeur fixe, et vous voyez des problèmes trop rarement. Cela en fait un encodage très dangereux si vous souhaitez prendre en charge Unicode.
Réponse
Oui, absolument.
Pourquoi? Cela concerne le code d’exercice .
Si vous regardez ces statistiques d’utilisation des points de code sur un grand corpus par Tom Christiansen, vous verrez que les points de code BMP trans-8 bits sont utilisés plusieurs ordres si la magnitude est supérieure aux points de code 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
Prenez le dicton TDD: « Le code non testé est du code cassé », et reformulez-le comme « le code non exercé est du code cassé », et pensez à la fréquence à laquelle les programmeurs doivent gérer des points de code non BMP.
Les bogues liés au fait de ne pas utiliser UTF-16 comme encodage à largeur variable sont beaucoup plus susceptibles de passer inaperçus que les bogues équivalents dans UTF-8 . Certains langages de programmation sont encore ne garantissez pas de vous donner UTF-16 au lieu de UCS-2, et certains langages de programmation dits de haut niveau offrent un accès à des unités de code au lieu de points de code (même C est censé vous donner accès aux points de code si vous utilisez wchar_t
, indépendamment de ce que certains plats formulaires peuvent faire).
Commentaires
- " Bogues liés au fait de ne pas traiter UTF-16 comme un encodage à largeur variable est beaucoup plus susceptible de passer inaperçu que les bogues équivalents en UTF-8. " Cest le cœur du problème, et donc la bonne réponse.
- Précisément. Si votre manipulation UTF-8 est bloquée, cela ' sera immédiatement évident. Si votre manipulation UTF-8 est gênée, vous ' ne le remarquerez que si vous insérez des caractères Han ou des symboles mathématiques inhabituels.
- Très vrai, mais de l’autre Par contre, à quoi servent les tests unitaires si vous devez compter sur la chance pour trouver des bogues sur des cas moins fréquents?
- @musiphil: alors, à quand remonte la dernière fois que vous avez créé un test unitaire pour les caractères non-BMP?
- Pour développer ma déclaration précédente: même avec UTF-8, vous ne pouvez pas être assuré que vous avez couvert tous les cas après avoir vu seulement quelques exemples de travail. Idem avec UTF-16: vous devez tester si votre code fonctionne à la fois avec des non-substituts et avec des substituts. (Quelquun pourrait même affirmer que UTF-8 a au moins quatre cas majeurs alors que UTF-16 nen a que deux.)
Réponse
Je dirais que penser que lUTF-16 pourrait être considéré comme dangereux signifie que vous devez acquérir une meilleure compréhension de lUnicode .
Puisque jai été critiqué pour avoir présenté mon opinion sur une question subjective, laissez-moi élaborer. Quest-ce qui vous dérange exactement à propos de lUTF-16? Préférez-vous que tout soit encodé en UTF-8? UTF-7? Ou Que diriez-vous de UCS-4? Bien sûr, certaines applications ne sont pas conçues pour gérer tous les codes de caractère unique là-bas – mais elles sont nécessaires, en particulier dans le domaine mondial de linformation daujourdhui, pour la communication entre les frontières internationales.
Mais vraiment, si vous pensez que UTF-16 devrait être considéré comme dangereux parce quil est déroutant ou peut être mal implémenté (Unicode peut certainement lêtre), alors quelle méthode de codage de caractères serait considérée comme non nuisible?
EDIT: Pour clarifier: Pourquoi considérer les implémentations incorrectes dune norme comme le reflet de la qualité de la norme elle-même? Comme dautres lont noté par la suite, le simple fait quune application utilise un outil de manière inappropriée ne signifie pas que loutil lui-même est défectueux. Si tel était le cas, nous pourrions probablement dire des choses comme « var mot-clé considéré comme nuisible », ou « threading considéré comme nuisible ». Je pense que la question confond la qualité et la nature de la norme avec les difficultés de nombreux programmeurs à mettre en œuvre et de lutiliser correctement, ce qui, selon moi, provient davantage de leur manque de compréhension du fonctionnement de lunicode, plutôt que de lunicode lui-même.
Commentaires
- -1: Que diriez-vous de traiter certains des objets dArtyom ' Ons, plutôt que de simplement le fréquenter?
- BTW: Quand jai commencé à écrire cet article, je voulais presque écrire " Est-ce que Joel on Softeare article dUnicode devrait être considéré nuisibles " car il y a beaucoup derreurs. Par exemple: lencodage utf-8 prend jusquà 4 caractères et non 6. De plus, il ne fait pas la distinction entre UCS-2 et UTF-16 qui sont vraiment différents – et causent en fait les problèmes dont je parle.
- En outre, il convient de noter que lorsque Joel a écrit cet article, la norme UTF-8 était de 6 octets, et non de 4. La RFC 3629 a changé la norme en 4 octets plusieurs mois APRÈS avoir écrit larticle. Comme presque tout sur Internet, il est avantageux de lire à partir de plusieurs sources et dêtre conscient de lâge de vos sources. Le lien n’était pas ' t destiné à être la " fin, tout être ", mais plutôt un point de départ.
- Je voudrais pic: utf-8 ou utf-32 qui sont: codage à longueur variable dans presque tous les cas (y compris BMP) ou codage à longueur fixe toujours.
- @iconiK: Ne soyez pas stupide. UTF-16 n’est absolument pas le standard de facto de traitement de texte. Montrez-moi un langage de programmation plus adapté au traitement de texte que Perl, qui a toujours (enfin, depuis plus de une décennie) a utilisé des caractères abstraits avec une représentation UTF-8 sous-jacente en interne. Pour cette raison, chaque programme Perl gère automatiquement tout Unicode sans que lutilisateur doive constamment se balader avec des substituts idiots. La longueur dune chaîne est son nombre en points de code, pas en unités de code. Tout le reste est de la pure stupidité mettant les rétrocompatibilités.
Réponse
Il ny a rien de mal avec Utf- 16 encodage. Mais les langages qui traitent les unités 16 bits comme des caractères devraient probablement être considérés comme mal conçus. Avoir un type nommé « char
» qui ne représente pas toujours un caractère est assez déroutant. Étant donné que la plupart des développeurs sattendent à ce quun type char représente un point de code ou un caractère, une grande partie du code se cassera probablement lorsquil sera exposé à des caractères au-delà de BMP.
Notez cependant que même lutilisation de utf-32 ne signifie pas que chaque 32- le point de code binaire représentera toujours un caractère. En raison de la combinaison de caractères, un caractère réel peut être composé de plusieurs points de code. Unicode nest jamais banal.
BTW. Il existe probablement la même classe de bogues avec des plates-formes et des applications qui sattendent à ce que les caractères soient 8 bits, qui sont alimentés en Utf-8.
Commentaires
- Dans le cas de Java ', si vous regardez leur chronologie ( java.com/en/javahistory/timeline.jsp), vous voyez que le développement principal de String sest produit alors que Unicode était de 16 bits (il a changé en 1996). Ils ont dû se concentrer sur la capacité à gérer des points de code non BMP, doù la confusion.
- @Kathy: Ce nest pas vraiment une excuse pour C #, cependant. En général, je conviens quil devrait y avoir un type
CodePoint
, contenant un seul point de code (21 bits), un typeCodeUnit
, tenant une unité de code unique (16 bits pour UTF-16) et un typeCharacter
devraient idéalement supporter un graphème complet. Mais cela la rend fonctionnellement équivalente àString
… - Cette réponse a presque deux ans, mais je peux ' t aide mais commente-le. " Avoir un type nommé ' char ' qui ne représente pas toujours un personnage est joli " Et pourtant, les gens lutilisent tout le temps en C et autres pour représenter des données entières qui peuvent être stockées dans un seul octet.
- Et moi ' jai vu un lot de code C qui ne gère ' pas correctement lencodage des caractères.
- C # a une excuse différente: il a été conçu pour Windows, et Windows a été construit sur UCS-2 (il ' est très ennuyeux que même aujourdhui les API Windows ne puissent pas prend en charge UTF-8). De plus, je pense que Microsoft voulait la compatibilité Java (.NET 1.0 avait une bibliothèque de compatibilité Java, mais ils ont abandonné le support Java très rapidement – je ' je suppose que cela est dû à Sun ' contre MS?)
Réponse
Mon choix personnel est pour toujours utiliser UTF-8. Cest la norme sur Linux pour presque tout. Il est rétrocompatible avec de nombreuses applications héritées. Il y a une surcharge très minime en termes despace supplémentaire utilisé pour les caractères non latins par rapport aux autres formats UTF, et il y a une économie despace significative pour les caractères latins. Sur le Web, les langues latines règnent en maître, et je pense quelles le seront dans un avenir prévisible. Et pour répondre à lun des principaux arguments du message original: presque tous les programmeurs sont conscients que lUTF-8 contiendra parfois des caractères multi-octets. Tout le monde ne gère pas cela correctement, mais ils en sont généralement conscients, ce qui est plus que ce que lon peut dire pour UTF-16. Mais, bien sûr, vous devez choisir celui qui convient le mieux à votre application. Cest pourquoi il y en a plusieurs en premier lieu.
Commentaires
- UTF-16 est plus simple pour tout ce qui se trouve dans BMP, que ' s pourquoi il est si largement utilisé. Mais je ' suis fan de UTF-8 aussi, il na pas non plus de problèmes avec lordre des octets, ce qui fonctionne à son avantage.
- Théoriquement, oui. En pratique, il existe des choses telles que, par exemple, UTF-16BE, qui signifie UTF-16 en big endian sans nomenclature. Ce nest pas quelque chose que jai inventé, cest un encodage réel autorisé dans les balises ID3v2.4 (les balises ID3v2 sont nulles, mais sont malheureusement largement utilisées). Et dans de tels cas, vous devez définir lendianness de manière externe, car le texte lui-même ne contient ' aucune nomenclature. UTF-8 est toujours écrit dans un sens et ' ne pose pas un tel problème.
- Non, UTF-16 n’est pas plus simple. Cest plus dur. Il induit en erreur et vous trompe en pensant quil sagit dune largeur fixe. Tout ce code est cassé et dautant plus parce que vous ne le remarquez pas avant quil ne soit trop tard. CAS IN POINT: Je viens de trouver un autre bogue UTF-16 stupide dans les bibliothèques de base Java hier, cette fois dans String.equalsIgnoreCase, qui a été laissé dans UCS-2 braindeath buggery, et échoue donc sur 16/17 points de code Unicode valides. Depuis combien de temps ce code existe-t-il? Aucune excuse pour que ce soit buggy. UTF-16 conduit à la pure stupidité et à un accident qui attend de se produire. Exécutez en hurlant depuis UTF-16.
- @tchrist Il faut être un développeur très ignorant pour ne pas savoir que UTF-16 nest pas de longueur fixe. Si vous commencez par Wikipedia, vous lirez ce qui suit tout en haut: " Il produit un résultat de longueur variable dune ou deux unités de code 16 bits par point de code ". La FAQ Unicode dit la même chose: unicode.org/faq//utf_bom.html#utf16-1 . Je ne sais ' pas, comment UTF-16 peut tromper nimporte qui sil est écrit partout quil est de longueur variable. Quant à la méthode, elle na jamais été conçue pour UTF-16 et ne devrait ' être considérée comme Unicode, aussi simple que cela.
- @tchrist Avez-vous un source pour vos statistiques? Même si les bons programmeurs sont rares, je pense que cest bien, car nous devenons plus précieux. 🙂 En ce qui concerne les API Java, les parties à base de caractères peuvent éventuellement devenir obsolètes, mais ce nest pas une garantie quelles ne seront pas ' utilisées. Et ils nont certainement pas ' être supprimés pour des raisons de compatibilité.
Réponse
Eh bien, il existe un encodage qui utilise des symboles de taille fixe. Je veux certainement dire UTF-32. Mais 4 octets pour chaque symbole représentent trop beaucoup d’espace gaspillé, pourquoi l’utiliserions-nous dans des situations quotidiennes?
Pour moi, la plupart des problèmes proviennent du fait que certains logiciels sont tombés derrière la norme Unicode, mais nont pas été prompts à corriger la situation. Opera, Windows, Python, Qt – tous sont apparus avant que lUTF-16 ne soit largement connu ou même nexiste. Je peux cependant confirmer que dans Opera, Windows Explorer et Notepad, il ny a plus de problèmes avec les caractères en dehors de BMP (du moins sur mon PC). Mais de toute façon, si les programmes ne reconnaissent pas les paires de substitution, alors ils nutilisent pas UTF-16. Quels que soient les problèmes liés à lutilisation de tels programmes, ils nont rien à voir avec lUTF-16 lui-même.
Cependant, je pense que les problèmes des logiciels hérités avec uniquement le support BMP sont quelque peu exagérés. Les caractères en dehors de BMP ne sont rencontrés que dans des cas et des domaines très spécifiques. Selon la FAQ officielle Unicode , « même dans le texte dAsie de lEst, lincidence des paires de substitution devrait être bien inférieure à 1% de tout le stockage de texte en moyenne ».Bien sûr, les caractères en dehors de BMP ne devraient « pas être négligés car un programme nest pas conforme à Unicode sinon, mais la plupart des programmes ne sont pas destinés à travailler avec des textes contenant de tels caractères. Cest pourquoi sils ne le font pas » t le supporter, cest désagréable, mais pas une catastrophe.
Considérons maintenant lalternative. Si UTF-16 n’existait pas, alors nous n’aurions pas un codage bien adapté pour le texte non ASCII, et tous les logiciels créés pour UCS-2 devraient être complètement repensés pour rester conformes à Unicode. Ce dernier ne ferait probablement que ralentir ladoption dUnicode. De plus, nous naurions pas été en mesure de maintenir la compatibilité avec le texte dans UCS-2 comme le fait UTF-8 par rapport à ASCII.
Maintenant, en mettant de côté tous les problèmes hérités, quels sont les arguments contre lencodage Je doute vraiment que les développeurs de nos jours ne sachent pas que UTF-16 est de longueur variable, il est écrit partout avec Wikipedia. UTF-16 est beaucoup moins difficile à analyser que UTF-8, si quelquun a signalé la complexité comme un problème possible. De plus, il est faux de penser quil est facile de se tromper avec la détermination de la longueur de chaîne uniquement en UTF-16. Si vous utilisez UTF-8 ou UTF-32, vous devez toujours être conscient quun point de code Unicode ne signifie pas nécessairement un caractère. À part cela, je ne pense pas quil y ait quoi que ce soit de substantiel contre le codage.
Par conséquent, je ne pense pas que le codage lui-même devrait être considéré comme dangereux. UTF-16 est un compromis entre simplicité et compacité, et il « ny a aucun mal à utiliser ce qui est nécessaire là où il est nécessaire . Dans certains cas, vous devez rester compatible avec ASCII et vous avez besoin de UTF-8, dans certains cas, vous souhaitez travailler avec des idéogrammes Han et économiser de lespace en utilisant UTF-16, dans certains cas, vous avez besoin de représentations universelles de caractères en utilisant un -longueur encodage. Utilisez ce qui est plus approprié, faites-le correctement.
Commentaires
- Que ' est un point de vue anglo-centrique plutôt aveugle, Malcolm. Presque sur un pied dégalité avec " ASCII est assez bon pour les États-Unis – le reste du monde devrait nous correspondre ".
- En fait, je ' m de Russie et je rencontre des cyrilliques tout le temps (y compris mes propres programmes), donc je ne ' Je pense que jai une vision anglo-centrique. 🙂 Mentionner ASCII nest pas tout à fait approprié, car ' nest pas Unicode et ne prend pas ' t des caractères spécifiques. UTF-8, UTF-16, UTF-32 prennent en charge les mêmes jeux de caractères internationaux, ils sont juste destinés à être utilisés dans leurs domaines spécifiques. Et cest exactement ce que je veux dire: si vous utilisez principalement langlais, utilisez UTF-8, si vous utilisez principalement des cyrilliques, utilisez UTF-16, si vous utilisez des langues anciennes, utilisez UTF-32. Cest très simple.
- " Non vrai, les scripts asiatiques comme le japonais, le chinois ou larabe appartiennent également à BMP. Le BMP lui-même est en fait très volumineux et certainement assez grand pour inclure tous les scripts utilisés de nos jours " Tout cela est faux. BMP contient des caractères 0xFFFF (65536). Le chinois seul a plus que cela. Les normes chinoises (GB 18030) ont plus que cela. Unicode 5.1 a déjà alloué plus de 100 000 caractères.
- @Marcolm: " BMP lui-même est en fait très volumineux et certainement assez grand pour inclure tous les scripts utilisés aujourdhui " Non vrai. À ce stade, Unicode a déjà alloué environ 100K caractères, bien plus que BMP ne peut en accueillir. Il y a de gros morceaux de caractères chinois en dehors de BMP. Et certains dentre eux sont requis par GB-18030 (norme chinoise obligatoire). Dautres sont requis par les normes japonaises et coréennes (non obligatoires). Donc, si vous essayez de vendre quoi que ce soit sur ces marchés, vous avez besoin au-delà du support BMP.
- Tout ce qui utilise UTF-16 mais ne peut gérer que des caractères BMP étroits nutilise pas réellement UTF-16. Il est buggé et cassé. La prémisse de lOP est saine: UTF-16 est nocif, car il conduit n ï ve personnes à écrire du code cassé. Soit vous pouvez gérer le texte Unicode, soit vous ne le pouvez pas. Si vous ne pouvez pas, alors vous choisissez un sous-ensemble, qui est tout aussi stupide que le traitement de texte ASCII uniquement.
Réponse
Des années de travail dinternationalisation de Windows, en particulier dans les langues dAsie de lEst, mont peut-être corrompu, mais je me penche vers UTF-16 pour les représentations internes au programme des chaînes et UTF-8 pour le stockage réseau ou de fichiers de texte en clair. comme des documents. Cependant, UTF-16 peut généralement être traité plus rapidement sous Windows, ce qui constitue le principal avantage de l’utilisation de l’UTF-16 sous Windows.
Le passage à l’UTF-16 a considérablement amélioré l’adéquation de la gestion moyenne des produits texte international.Il ny a que quelques cas étroits où les paires de substitution doivent être prises en compte (suppressions, insertions et sauts de ligne, essentiellement) et le cas moyen est principalement un passage direct. Et contrairement aux encodages précédents comme les variantes JIS, UTF-16 limite les paires de substitution à une plage très étroite, donc la vérification est vraiment rapide et fonctionne en avant et en arrière.
Certes, cest à peu près aussi rapide correctement- codé UTF-8, aussi. Mais il ya aussi de nombreuses applications UTF-8 cassées qui codent incorrectement des paires de substitution comme deux séquences UTF-8. Donc, UTF-8 ne garantit pas non plus le salut.
IE gère raisonnablement bien les paires de substitution depuis 2000 ou plus, même sil les convertit généralement de pages UTF-8 en une représentation UTF-16 interne; I « Je suis assez sûr que Firefox a bien fait aussi les choses, donc je ne me soucie pas vraiment de ce que fait Opera.
UTF-32 (alias UCS4) est inutile pour la plupart des applications car il est si encombrant, cest donc à peu près un non-démarreur.
Commentaires
- Je nai ' commenter UTF-8 et les paires de substitution. Les paires de substitution ne sont quun concept significatif dans le codage UTF-16, nest-ce pas? cas, le problème est de lire incorrectement lUTF-16, pas décrire lUTF-8. Est-ce exact?
- Ce dont parle Jason ' est un logiciel qui implémente délibérément UTF-8 de cette façon: créer une paire de substitution, puis UTF-8 fr codez chaque moitié séparément. Le nom correct pour cet encodage est CESU-8, mais Oracle (par exemple) le dénature comme UTF-8. Java utilise un schéma similaire pour la sérialisation des objets, mais ' est clairement documenté comme " UTF-8 modifié " et uniquement à usage interne. (Maintenant, si nous pouvions simplement amener les gens à LIRE cette documentation et à arrêter dutiliser DataInputStream # readUTF () et DataOutputStream # writeUTF () de manière inappropriée …)
- AFAIK, UTF-32 est toujours un encodage à longueur variable, et pas égal à UCS4 qui est une plage spécifique de points de code.
- @Eonil, UTF-32 ne sera jamais distinguable de UCS4 que si nous avons un standard Unicode qui comporte quelque chose comme un UCS5 ou plus.
- @JasonTrue Pourtant, seuls les résultats sont égaux par coïncidence, non garantis par la conception. La même chose sest produite dans ladressage mémoire 32 bits, Y2K, UTF16 / UCS2. Ou avons-nous une garantie de cette égalité? Si cest le cas, je lutiliserais avec plaisir. Mais je ne ' pas vouloir écrire un code cassable possible . Jécris un code au niveau des caractères, et labsence de moyen garanti de transcoder entre le point de code UTF < – > me dérange beaucoup .
Réponse
UTF-8 est définitivement la voie à suivre, éventuellement accompagné de UTF-32 pour les utiliser dans des algorithmes qui nécessitent un accès aléatoire haute performance (mais qui ignore la combinaison de caractères).
Les UTF-16 et UTF-32 (ainsi que leurs variantes LE / BE) souffrent de problèmes dendianess, ils devraient donc ne jamais être utilisé en externe.
Commentaires
- Laccès aléatoire à temps constant est également possible avec UTF-8, utilisez simplement des unités de code plutôt que des points de code. Vous avez peut-être besoin d’un accès aléatoire réel à un point de code, mais je ' n’a jamais vu de cas d’utilisation, et vous ' êtes tout aussi susceptible de vouloir accès aléatoire au cluster de graphèmes à la place.
Réponse
UTF-16? définitivement nuisible. Juste mon grain de sel ici, mais il y a exactement trois encodages acceptables pour le texte dans un programme:
- ASCII: lorsquil sagit de choses de bas niveau (par exemple: des microcontrôleurs) qui ne peuvent rien se permettre de mieux
- UTF8: stockage dans des supports à largeur fixe tels que des fichiers
-
points de code entiers (« CP »?): un tableau des plus grands entiers qui conviennent à votre langage de programmation et plate-forme (décroît en ASCII dans la limite des faibles résorces). Doit être int32 sur les ordinateurs plus anciens et int64 sur tout ce qui a un adressage 64 bits.
-
De toute évidence, les interfaces avec le code hérité quel encodage est nécessaire pour que lancien code fonctionne correctement.
Commentaires
- @simon buchan, le
U+10ffff
max sortira de la fenêtre quand (pas si) ils seront à court de points de code. Cela dit, utiliser int32 sur un système p64 pour la vitesse est probablement sûr, car je doute quils ' Je vais dépasserU+ffffffff
avant que vous est obligé de réécrire votre code pour les systèmes 128 bits vers 2050. (Cest le point de " utiliser le plus grand entier qui est pratique " par opposition à " le plus grand disponible " (qui serait probablement int256 ou bignums ou quelque chose comme ça).) - @David: Unicode 5.2 code 107 361 points de code.Il y a 867 169 points de code inutilisés. " quand " est tout simplement idiot. Un point de code Unicode est défini comme un nombre compris entre 0 et 0x10FFFF, une propriété dont dépend UTF-16. (De plus, 2050 semble beaucoup trop basse pour les systèmes 128 bits lorsquun système 64 bits peut contenir lintégralité dInternet dans lespace dadressage de '.)
- @David: Votre " quand " faisait référence à un manque de points de code Unicode, pas à un commutateur 128 bits qui, oui, sera dans les prochains siècles. Contrairement à la mémoire, il ny a pas de croissance exponentielle des caractères, donc le consortium Unicode a spécifiquement garanti quil nallouera jamais de point de code au-dessus de
U+10FFFF
. Cest vraiment une de ces situations où 21 bits suffisent pour nimporte qui. - @Simon Buchan: Au moins jusquau premier contact. 🙂
- Unicode utilisé pour garantir quil ny aurait pas de points de code au-dessus de U + FFFF également.
Réponse
Unicode définit des points de code jusquà 0x10FFFF (1 114 112 codes), toutes les applications exécutées dans un environnement multilingue traitant avec des chaînes / noms de fichiers, etc. devrait gérer cela correctement.
Utf-16 : ne couvre que 1 112 064 codes. Bien que ceux à la fin de Unicode proviennent des plans 15-16 (zone dutilisation privée). Il ne peut plus se développer dans le futur, sauf en cas de rupture du concept Utf-16 .
Utf-8 : couvre théoriquement 2 216 757 376 codes. La plage actuelle de codes Unicode peut être représentée par une séquence de 4 octets au maximum. Il ne souffre pas du problème de ordre doctets , il est « compatible » avec ascii.
Utf-32 : couvre théoriquement 2 ^ 32 = 4 294 967 296 codes. Actuellement, il nest pas codé en longueur variable et ne le sera probablement pas à lavenir.
Ces faits sont explicites. Je ne comprends pas le fait de préconiser une utilisation générale de Utf-16 . Il est codé en longueur variable (ne peut pas être consulté par index), il a des problèmes pour couvrir toute la plage Unicode même actuellement, Lordre des octets doit être géré, etc. Je ne vois aucun avantage si ce nest quil est utilisé nativement sous Windows et dans dautres endroits. Même si lors de lécriture de code multi-plateforme, il est probablement préférable dutiliser Utf-8 de manière native et deffectuer des conversions uniquement aux points finaux de manière dépendante de la plate-forme (comme déjà suggéré). Lorsquun accès direct par index est nécessaire et que la mémoire ne pose pas de problème, Utf-32 doit être utilisé.
Le principal problème est que de nombreux programmeurs travaillant avec Windows Unicode = Utf-16 ne savent même pas ou ignorent le fait que il est codé en longueur variable.
La façon dont il est généralement utilisé sur la plate-forme * nix est plutôt bonne, chaînes c (char *) interprétées comme Utf-8 codées, chaînes c larges (wchar_t *) interprétées comme Utf-32 .
Commentaires
- Remarque: UTF -16 couvre tous les Unicode car le consortium Unicode a décidé que 10FFFF est la plage TOP dUnicode et défini la longueur maximale de 4 octets UTF-8 et la plage explicitement exclue 0xD800-0xDFFF de la plage de points de code valide et cette plage est utilisée pour la création dun substitut paires. Ainsi, tout texte Unicode valide peut être représenté avec chacun de ces encodages. Également sur la croissance vers le futur. Cela ne ' t semble quun million de points de code ne suffirait pas dans un avenir lointain.
- @Kerrek: Incorrect: UCS-2 nest pas un Unicode valide codage. Tous les encodages UTF- * par définition peuvent représenter nimporte quel point de code Unicode autorisé pour léchange. UCS-2 peut représenter beaucoup moins que cela, plus un peu plus. Répétez: UCS-2 nest pas un encodage Unicode valide, tout plus que lASCII lest.
- " Je ne comprends pas lidée de préconiser lutilisation générale de Utf- 8 . Il est codé en longueur variable (ne peut être accédé par index) "
- @Ian Boyd, la nécessité daccéder au caractère individuel dune chaîne dans un modèle daccès aléatoire est incroyablement exagéré. Cest à peu près aussi courant que de vouloir calculer la diagonale dune matrice de caractères, ce qui est super rare. Les chaînes sont pratiquement toujours traitées séquentiellement, et depuis laccès au caractère UTF-8 N + 1 étant donné que vous êtes à UTF-8 car N est O (1), il ny a pas de problème. Il est extrêmement peu nécessaire de créer un accès aléatoire aux chaînes. Que vous pensiez que cela vaut la peine de passer à lUTF-32 au lieu de lUTF-8, cest votre propre opinion, mais pour moi, ce nest pas du tout un problème.
- @tchrist, je laccorderai vos chaînes sont pratiquement toujours traitées séquentiellement si vous incluez une itération inverse comme " séquentielle " et étirez cette petite comparaison supplémentaire de la fin de une chaîne à une chaîne connue. Deux scénarios très courants consistent à tronquer les espaces à partir de la fin des chaînes et à vérifier l’extension de fichier à la fin d’un chemin.
Réponse
Ajoutez ceci à la liste:
Le scénario présenté est simple (dautant plus simple que je vais le présenter ici quil ne létait à lorigine! ): 1.A WinForms TextBox se trouve sur un formulaire, vide. Il a une longueur maximale définie sur 20 .
2.Lutilisateur tape dans la zone de texte, ou peut-être colle du texte dedans.
3.Peu importe ce que vous tapez ou collez dans la zone de texte, vous êtes limité à 20, bien quil émettra un bip sympathique au texte au-delà du 20 (YMMV ici; jai changé mon schéma sonore pour me donner cet effet!).
4. Le petit paquet de texte est ensuite envoyé ailleurs, pour commencer une aventure passionnante.
Maintenant, cest un scénario facile, et nimporte qui peut lécrire, pendant son temps libre. Je viens de lécrire moi-même dans plusieurs langages de programmation en utilisant WinForms, car je mennuyais et ne lavais jamais essayé auparavant. Et avec du texte dans plusieurs langues réelles parce que je suis câblé de cette façon et que jai plus de dispositions de clavier que nimporte qui dans tout lunivers flippant.
Jai même nommé le formulaire Magic Carpet Ride , pour aider à atténuer lennui.
Cela na pas fonctionné, pour ce que ça vaut.
À la place, jai saisi le 20 caractères dans mon formulaire Magic Carpet Ride :
0123401234012340123 𠀀
Oh oh.
Ce dernier caractère est U + 20000, le premier Extension B idéogramme dUnicode (alias U + d840 U + dc00, à ses amis proches dont il na pas honte de se faire défrober, pour ainsi dire, devant) ….
Et maintenant nous avons un jeu de balle.
Parce que quand TextBox. MaxLength parle de
Obtient ou définit le nombre maximum de caractères pouvant être saisis manuellement dans la zone de texte.
ce que cela signifie vraiment est
Obtient ou définit le nombre maximum de codage UTF-16 LE Les unités qui peuvent être entrées manuellement dans la zone de texte et tronqueront sans pitié la merde vivante de toute chaîne qui tente de jouer à des jeux mignons avec la notion de caractère linguistique que seule une personne aussi obsédée que ce camarade de Kaplan trouvera offensant (bon sang, il doit en savoir plus!).
Je « vais essayer de voir comment mettre à jour le document ….
Lecteurs réguliers qui souvenez-vous que ma série UCS-2 à UTF-16 notera mon mécontentement avec la notion simpliste de TextBox.MaxLength et comment il doit gérer au minimum ce cas où son comportement draconien crée une séquence illégale, une séquence que dautres parties du .Net Framework peuvent lancer une
- System.Text.EncoderFallbackException : Impossible de traduire le caractère Unicode \ uD850 à lindex 0 vers la page de code spécifiée. *
exception si vous passez cette chaîne ailleurs dans le .Net Framework (comme mon collègue Dan Thompson le faisait).
Maintenant, daccord, peut-être que la série complète des UCS-2 à UTF-16 est hors de portée de beaucoup.
Mais nest pas « Est-il raisonnable de sattendre à ce que TextBox.Text ne produise pas un System.String qui » ne provoquera pas le lancement dun autre élément du .Net Framework? » Je veux dire, ce nest pas comme sil y avait une chance sous la forme dun événement sur le contrôle qui vous informe de la troncature à venir où vous pouvez facilement ajouter la validation plus intelligente – validation que le contrôle lui-même ne me dérange pas de faire. aller jusquà dire que ce contrôle punk rompt un contrat de sécurité qui pourrait même entraîner des problèmes de sécurité si vous pouvez classer provoquant des exceptions inattendues pour mettre fin à une application comme une sorte de déni de service grossier. Pourquoi un traitement ou une méthode WinForms ou lalgorithme ou la technique produisent des résultats non valides?
Source: Michael S.Blog Kaplan MSDN
Commentaires
- Merci, très bon lien! Je ' lai ajouté à la liste des problèmes dans la question.
Réponse
Je ne dirais pas nécessairement que lUTF-16 est nocif. Ce nest pas élégant, mais il remplit son rôle de rétrocompatibilité avec UCS-2, tout comme le GB18030 avec GB2312, et UTF-8 avec ASCII.
Mais apporter un changement fondamental à la structure dUnicode à mi-chemin, après que Microsoft et Sun aient construit dénormes API autour de caractères 16 bits, était nuisible. Le fait de ne pas faire connaître le changement était plus dangereux.
Commentaires
- UTF-8 est un sur-ensemble dASCII , mais UTF-16 nest PAS un sur-ensemble de UCS-2. Bien que presque un surensemble, un codage correct de UCS-2 en UTF-8 aboutit à labomination connue sous le nom de CESU-8; UCS-2 na ' t avoir des substituts, juste des points de code ordinaires, ils doivent donc être traduits comme tels. Le véritable avantage de lUTF-16 est quil est ' plus facile de mettre à niveau une base de code UCS-2 quune réécriture complète pour UTF-8. Cest drôle, hein?
- Bien sûr, techniquement, UTF-16 nest pas ' un sur-ensemble de UCS-2, mais quand U + D800 à U + DFFF ont-ils jamais été utilisé pour tout sauf les substituts UTF-16?
- Cela na pas dimportance '. Tout traitement autre que le passage aveugle du flux doctets vous oblige à décoder les paires de substitution, ce que vous pouvez ' faire si vous ' traiter comme UCS-2.
Réponse
UTF-16 est le meilleur compromis entre manipulation et espace et cest pourquoi la plupart des grandes plates-formes (Win32, Java, .NET) lutilisent pour la représentation interne des chaînes.
Commentaires
- -1 car UTF-8 est susceptible dêtre plus petit ou peu différent. Pour certains scripts asiatiques, UTF-8 est de trois octets par glyphe alors que UTF-16 nest que de deux, mais cest équilibré par UTF-8 étant seulement un octet pour ASCII (qui apparaît souvent même dans les langues asiatiques dans les noms de produits, les commandes et autres). De plus, dans lesdites langues, un glyphe transmet plus dinformations quun caractère latin donc il est justifié pour quil prenne plus de place.
- Je nappellerais pas combiner le travail Le premier côté des deux options est un bon compromis.
- Il ' nest pas plus facile que UTF-8. Il est également ' de longueur variable.
- Laissant de côté les débats sur les avantages de l’UTF-16: ce que vous avez cité n’est pas le raison pour Windows, Java ou .NET utilisant UTF-16. Windows et Java remontent à une époque où Unicode était un encodage 16 bits. UCS-2 était un choix raisonnable à lépoque. Lorsque Unicode est devenu un encodage 21 bits, la migration vers UTF-16 était le meilleur choix des plates-formes existantes. Cela navait rien à voir avec la facilité de manipulation ou les compromis despace. Cest ' quune question dhéritage.
- .NET hérite de lhéritage Windows ici.
Réponse
Je « nai jamais compris le sens de UTF-16. Si vous voulez la représentation la plus efficace en espace, utilisez UTF-8. Si vous voulez pouvoir Traitez le texte comme une longueur fixe, utilisez UTF-32. Si vous ne voulez ni lun ni lautre, utilisez UTF-16. Pire encore, puisque tous les caractères communs (plan multilingue de base) en UTF-16 tiennent dans un seul point de code, des bogues qui supposent que UTF-16 est de longueur fixe sera subtile et difficile à trouver, alors que si vous essayez de le faire avec UTF-8, votre code échouera rapidement et bruyamment dès que vous essayez de vous internationaliser.
Réponse
Comme je ne peux pas encore commenter, je poste ceci comme réponse, car il semble que je ne puisse pas contacter autrement les auteurs de utf8everywhere.org
. Cest « dommage que je ne reçoive pas automatiquement le privilège de commentaire, car jai assez de réputation sur les autres échanges de pile.
Ceci est censé être un commentaire à la réponse : Oui, UTF-16 doit être considéré comme dangereux .
Une petite correction:
Pour éviter de passer accidentellement un UTF-8 char*
dans les versions de chaîne ANSI des fonctions Windows-API, il faut définissez UNICODE
, et non _UNICODE
. _UNICODE
mappe des fonctions telles que _tcslen
à wcslen
, pas MessageBox
à MessageBoxW
. Au lieu de cela, la définition UNICODE
prend en charge ce dernier. Pour preuve, ceci provient de len-tête WinUser.h
de MS Visual Studio 2005 « :
#ifdef UNICODE #define MessageBox MessageBoxW #else #define MessageBox MessageBoxA #endif // !UNICODE
Au minimum, cette erreur doit être corrigée sur utf8everywhere.org
.
Une suggestion:
Peut-être que le guide devrait contenir un exemple dutilisation explicite du Wide- version chaîne dune structure de données, pour quil soit moins facile de la manquer / de loublier.Lutilisation de versions à chaîne large de structures de données en plus de lutilisation de versions de fonctions à chaîne large rend encore moins probable que lon appelle accidentellement une version chaîne ANSI dune telle fonction.
Exemple de lexemple:
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); }
Commentaires
- Accepté; Merci! Nous mettrons à jour le document. Le document doit encore être développé et ajouté des informations sur les bases de données. Nous sommes heureux de recevoir des contributions de libellés.
- @PavelRadzivilovsky
_UNICODE
est toujours là 🙁 - merci pour le rappel. Cubus, Jelle, Souhaitez-vous quun utilisateur accède à notre SVN?
- @Pavel Bien sûr, je lapprécierais!
- @JelleGeerts: Je mexcuse pour ce retard. Vous pouvez toujours nous contacter par nos e-mails (lien du manifeste) ou Facebook. Nous sommes faciles à trouver. Bien que je pense que nous ayons résolu le problème que vous avez soulevé ici (et je vous en ai crédité), lensemble des débats UTF-8 vs UTF-16 sont toujours pertinents. Si vous en avez plus à contribuer nhésitez pas à nous contacter via ces canaux privés.
Réponse
Quelquun a dit que UCS4 et UTF-32 étaient Même. Non, mais je sais ce que vous voulez dire. Lun deux est un encodage de lautre, cependant. Jaurais aimé quils aient pensé à spécifier lendianness dès le premier afin que nous nayons pas la bataille dendianess livrée ici aussi. Nont-ils pas pu voir ça venir? Au moins UTF-8 est le même partout re (sauf si quelquun suit la spécification dorigine avec 6 octets).
Si vous utilisez UTF-16, vous devez inclure la gestion des caractères multi-octets. Vous ne pouvez pas aller au Nième caractère en indexant 2N dans un tableau doctets. Vous devez le parcourir, ou avoir des index de caractères. Sinon, vous avez écrit un bogue.
Le projet de spécification actuel de C ++ dit que UTF-32 et UTF-16 peuvent avoir des variantes little-endian, big-endian et non spécifiées. Ah bon? Si Unicode avait spécifié que tout le monde devait faire le petit-boutiste depuis le début, tout aurait été plus simple. (Jaurais été bien avec le big-endian aussi.) Au lieu de cela, certaines personnes lont implémenté dans un sens, dautres dans lautre, et maintenant nous sommes coincés avec la bêtise pour rien. Parfois, il est embarrassant dêtre un ingénieur logiciel.
Commentaires
- Une extrémité non spécifiée est censée inclure la nomenclature comme premier caractère, utilisé pour déterminer la manière dont la chaîne doit être lue. UCS-4 et UTF-32 sont en effet les mêmes de nos jours, cest-à-dire une valeur numérique UCS entre 0 et 0x10FFFF stockée dans un entier de 32 bits.
- @Tronic: Techniquement, ce nest pas vrai. Bien que UCS-4 puisse stocker nimporte quel entier 32 bits, il est interdit à UTF-32 de stocker les points de code non-caractères qui ne sont pas autorisés pour léchange, tels que 0xFFFF, 0xFFFE et tous les substituts. UTF est un encodage de transport, pas un encodage interne.
- Les problèmes dendianness sont inévitables tant que différents processeurs continuent à utiliser des ordres doctets différents. Cependant, cela aurait pu être bien sil y avait un ordre doctets " préféré " pour le stockage des fichiers en UTF-16.
- Même si UTF-32 est de largeur fixe pour les points de code , il n’est pas de largeur fixe pour les caractères . (Vous avez entendu parler de quelque chose appelé " combinant des caractères "?) Vous pouvez donc ' aller au N ' e caractère simplement en indexant 4N dans le tableau doctets.
Réponse
Je ne pense pas que ce soit dangereux si le développeur est suffisamment prudent.
Et ils devraient accepter ce compromis s’ils savent bien aussi.
En tant que développeur de logiciels japonais, je trouve UCS-2 assez grand et la limitation de lespace simplifie apparemment la logique et réduit la mémoire dexécution, donc utiliser utf-16 sous la limitation UCS-2 est assez bon.
Il existe un système de fichiers ou une autre application qui suppose que les points de code et les octets sont proportionnels, de sorte que le nombre de points de code brut peut être garanti pour être adapté à un stockage de taille fixe.
Un exemple est NTFS et VFAT spécifiant UCS-2 comme encodage de stockage de leur nom de fichier.
Si ces exemples veulent vraiment sétendre pour prendre en charge UCS-4, je pourrais accepter dutiliser utf-8 pour tout de toute façon, mais la longueur fixe a de bons points comme:
- peut garantir la taille par longueur (la taille des données et la longueur du point de code sont proportionnelles)
- peut utiliser le numéro de codage pour la recherche de hachage
- les données non compressées sont de taille raisonnable (par rapport à utf-32 / UCS-4)
À lavenir, lorsque la mémoire / la puissance de traitement sont bon marché, même dans tous les périphériques intégrés, nous pouvons accepter que le périphérique soit un peu lent pour des erreurs de cache ou des défauts de page supplémentaires et de la mémoire supplémentaire utilisation, mais cela ne se produira pas dans un avenir proche je suppose …
Commentaires
- Pour ceux qui liront ce commentaire, il convient de noter que UCS- 2 nest pas la même chose que UTF-16. Veuillez rechercher les différences pour comprendre.
Réponse
« Devrait lun des plus populaires encodages, UTF-16, être considérés comme nuisibles? «
Très probablement, mais les alternatives ne devraient pas nécessairement être considérées comme étant bien meilleures.
Le problème fondamental est quil existe de nombreux concepts différents concernant: les glyphes, les caractères, les points de code et les séquences doctets. Le mappage entre chacun dentre eux nest pas trivial, même à laide dune bibliothèque de normalisation. (Par exemple, certains caractères dans les langues européennes qui sont écrits avec un script latin ne sont pas écrits avec un seul point de code Unicode. Et cest à la fin la plus simple de la complexité!) Cela signifie que tout est correct est assez étonnamment difficile; il faut sattendre à des bugs bizarres (et au lieu de simplement se plaindre deux ici, informez les responsables du logiciel concerné).
La seule façon dont UTF- 16 peut être considéré comme nuisible par rapport à, disons, UTF-8, cest quil a une manière différente de coder des points de code en dehors du BMP (comme une paire de substituts). Si le code souhaite accéder ou itérer par point de code, cela signifie quil doit être conscient de la différence. OTOH, cela signifie quun corps substantiel de code existant qui suppose des « caractères » peut toujours être inséré dans une quantité de deux octets – une hypothèse assez courante, si elle est fausse – peut à au moins continuer à travailler sans tout reconstruire. En d’autres termes, au moins vous pouvez voir ces caractères s qui ne sont pas gérées correctement!
Je retourne votre question et dis que tout ce putain de broutage dUnicode devrait être considéré comme dangereux et que tout le monde devrait utiliser un encodage 8 bits, sauf Jai vu (au cours des 20 dernières années) où cela mène: horrible confusion sur les différents encodages ISO 8859, plus lensemble de ceux utilisés pour le cyrillique et la suite EBCDIC, et… eh bien, Unicode pour tous ses défauts bat cela . Si seulement ce nétait pas un si mauvais compromis entre différents pays, des malentendus.
Commentaires
- Connaissant notre chance, dans quelques années nous ' Nous allons nous retrouver à manquer despace en UTF-16. Meh.
- Le problème fondamental est que le texte est trompeusement difficile. Aucune approche pour représenter ces informations de manière numérique ne peut être simple. ' est la même raison pour laquelle les dates sont difficiles, les calendriers sont difficiles, le temps est dur, les noms personnels sont durs, les adresses postales sont difficiles: chaque fois que les machines numériques se croisent avec des constructions culturelles humaines, la complexité éclate. C’est une réalité de la vie. Les humains ne fonctionnent pas sur la logique numérique.