Confus au sujet de C++'S std:: wstring, UTF-16, UTF-8 et l'affichage des chaînes dans une interface graphique windows

je travaille sur un programme C++ en anglais Pour Windows où on nous a dit" always use std::wstring", mais il semble que personne dans l'équipe n'a vraiment beaucoup de compréhension au-delà de cela.

j'ai déjà lu la question intitulée "std::wstring VS std::string . C'était très utile, mais je ne comprends toujours pas comment appliquer toute cette information à mon problème.

le programme sur lequel je travaille affiche des données une interface graphique Windows. Les données sont enregistrées au format XML. Nous transformons souvent ce XML à L'aide de XSLT en HTML ou XSL:FO à des fins de déclaration.

mon sentiment basé sur ce que j'ai Lu est que le HTML devrait être encodé en UTF-8. Je sais très peu de choses sur le développement de GUI, mais le petit passage que j'ai lu indique que les trucs GUI sont tous basés sur des chaînes encodées UTF-16.

j'essaie de comprendre où ça me mène. Disons que nous décidons que tout notre persisté les données doivent être codées en langage XML UTF-8. Cela signifie-t-il que pour afficher des données persistées dans une composante de L'interface utilisateur, je devrais réellement effectuer une sorte de processus de conversion explicite UTF-8 à UTF-16?

je pense que mon explication pourrait avoir besoin de clarification, donc je vais essayer de fournir que si vous avez des questions.

15
demandé sur Community 2010-03-27 03:53:06

5 réponses

de Windows NT4, basé sur Unicode codé chaînes, oui. Les premières versions étaient basées sur UCS-2, qui est le prédécesseur ou UTF-16, et ne supporte donc pas tous les caractères que UTF-16 fait. Les versions suivantes sont basées sur UTF-16. Cependant, tous les eso ne sont pas basés sur UTF-16/UCS-2. *les systèmes nix, par exemple, sont basés sur UTF-8 à la place.

UTF-8 est un très bon choix pour stocker des données de manière persistante. Il est un encodage universellement supporté dans tous Il s'agit d'un bon équilibre entre la taille des données et la compatibilité des données sans perte.

Oui, vous devez analyser le XML, en extraire les informations nécessaires, et le décoder et le transformer en quelque chose que L'interface utilisateur peut utiliser.

7
répondu Remy Lebeau 2010-03-27 01:06:49

AFAIK quand vous travaillez avec std:: wstring sur Windows en C++ et stocker en utilisant UTF-8 dans les fichiers (ce qui semble bon et raisonnable), puis vous devez convertir les données en UTF-8 lors de l'écriture dans un fichier, et convertir de nouveau en UTF-16 lors de la lecture d'un fichier. Consultez ce lien: écrire des fichiers UTF-8 en C++ .

Je m'en tiendrais au défaut de Visual Studio du projet - > Propriétés - > Propriétés de Configuration -> Généralités - > jeu de caractères -> utilisation Jeu de caractères Unicode, utilisez le type wchar_t (i.e. avec std::wstring) et pas utilisez le type TCHAR. (P. ex. Je voudrais juste utiliser la version wcslen de strlen et pas _tcslen.)

5
répondu Jim Flood 2010-03-27 02:49:34

std:: wstring est techniquement UCS-2: deux octets sont utilisés pour chaque caractère et les tables de code principalement de la carte au format Unicode. il est important de comprendre que UCS-2 n'est pas le même que UTF-16! UTF-16 permet des "paires de substitution" afin de représenter des caractères qui sont en dehors de la plage de deux octets, mais UCS-2 utilise exactement deux octets pour chaque caractère, période.

la meilleure règle pour votre situation est de faire votre le transcodage quand vous lisez et écrivez sur le disque. Une fois en mémoire, conservez-le au format UCS-2. Windows APIs le lira comme si C'était UTF-16 (ce qui est à dire, alors que std::wstring ne comprend pas le concept de paires de substitution, si vous les créez manuellement (ce que vous ne ferez pas, si votre seule langue est l'anglais), Windows les lira).

chaque fois que vous lisez des données dans ou hors des formats de sérialisation (tels que XML) dans les jours modernes, vous aurez probablement besoin de faire transcodage. C'est un fait déplaisant et très malheureux de la vie, mais inévitable puisque Unicode est un codage de caractères de largeur variable et la plupart des opérations basées sur les caractères en C++ sont faites comme des tableaux, pour lesquels vous avez besoin d'espacement cohérent.

cadres supérieurs, tels que .NET, obscurcissent la plupart des détails, mais dans les coulisses, ils manipulent le transcodage de la même manière: en changeant les données de largeur variable en chaînes de largeur fixe, en les manipulant, puis en changeant les remettre dans des codages de largeur variable lorsque requis pour la sortie.

4
répondu Dan Story 2010-03-27 01:12:58

l'un des avantages d'utiliser std::wstring sur Windows pour les chaînes liées à GUI, est qu'en interne tous les appels API Windows utilisent et fonctionnent sur UTF-16. Si vous avez déjà remarqué, il y a 2 versions de tous les appels Win32 API qui prennent des arguments string. Par exemple," MessageBoxA "et"MessageBoxW". Les deux définitions existent , et en fait vous pouvez appeler soit vous voulez, mais si est inclus avec le support Unicode activé, alors la suivante se produira:

#define MessageBox MessageBoxW

alors vous accédez à TCHAR et autres astuces de Microsoft pour essayer de rendre plus facile de traiter avec APIs qui ont à la fois une version ANSI et Unicode. En bref, vous pouvez appeler l'un ou l'autre, mais sous le capot le noyau Windows en Unicode basé, de sorte que vous allez payer le coût de conversion en Unicode pour chaque chaîne acceptant L'appel D'API Win32 si vous n'utilisez pas la version char large.

UTF-16 et le noyau de Windows utiliser

3
répondu cpalmer 2010-03-27 01:07:50

même si vous dites que vous n'avez que l'anglais dans vos données, vous vous trompez probablement. Puisque nous sommes dans un monde global, maintenant, les noms/adresses/etc ont des caractères étrangers. OK, je ne sais pas quel type de données vous avez, mais généralement je dirais construisez votre application pour supporter UNICODE à la fois pour le stockage de données et l'affichage de données à l'utilisateur. Cela suggère D'utiliser XML avec UTF-8 pour stocker et UNICODE les versions des appels Windows lorsque vous faites GUI. Et depuis Windows GUI utilise UTF-16, où chaque token est 16-bits, je suggère de stocker les données dans l'application dans un 16 bits de large chaîne. Et je suppose que votre compilateur pour windows aurait std::wstring de 16-bit.

alors vous devez faire beaucoup de conversion entre UTF-16 et UTF-8. Faites cela avec une bibliothèque existante, comme par exemple ICU .

1
répondu jpyllman 2010-03-27 02:03:46