Comment puis-je obtenir STL std :: string pour travailler avec unicode sur Windows?
Dans mon entreprise nous avons une multi-plateforme(Linux & Windows) bibliothèque qui contient notre propre extension de la STL std::string, cette classe fournit toutes sortes de fonctionnalités sur le dessus de la corde; la scission, du format, de/à partir base64, etc. Récemment, nous avons vu la nécessité de faire de cette chaîne unicode "amicale" fondamentalement, il doit en charge les caractères Chinois, le Japonais, l'arabe, etc. Après une première recherche, cela semble très bien côté Linux, car chaque chose est en soi UTF-8, mais j'ai du mal avec le côté Windows; est-il une astuce pour obtenir la STL std::string pour travailler en UTF-8 sur windows? Est-il même possible? Est-il un meilleur moyen? Idéalement nous garder nous-mêmes basés sur les std::string car c'est ce qui la classe string est basé sur Linux.
Merci,
source d'informationauteur NSA
Vous devez vous connecter pour publier un commentaire.
Il ya plusieurs idées fausses dans votre question.
Ni C++, ni la STL traiter avec des encodages.
std::string
est essentiellement une chaîne de octetspas caractères. Donc, vous ne devriez avoir aucun problème farce codé en UTF-8 Unicode. Cependant, gardez à l'esprit que tous lesstring
fonctions également travailler sur des octets, de sorte quemyString.length()
vous donnera le nombre d'octets, et non pas le nombre de caractères.Linux est pas intrinsèquement UTF-8. La plupart des distributions de nos jours par défaut en UTF-8, mais il ne doit pas être invoqué.
Oui, en étant plus conscient de lieux et d'encodages.
Windows a deux appels de fonction pour tout ce qui requiert de texte, un FoobarA() et un FoobarW(). L' *W() les fonctions codé en UTF-16 chaînes, l' *() prend des chaînes dans la page de codes actuelle. Cependant, Windows ne supporte pas l'UTF-8 code de la page, donc vous ne pouvez pas l'utiliser directement dans ce sens avec l' *() fonctions, ni voulez-vous dépendent que définie par les utilisateurs. Si vous voulez "Unicode" dans Windows, utilisez l'compatibles Unicode (*W) de fonctions. Il ya des tutoriels là-bas, Googler "Unicode Windows tutoriel" devrait vous aider un peu.
Si vous stockez des données UTF-8 dans une std::string, puis avant de passer à Windows, convertir en UTF-16 (Windows fournit des fonctions telles), et puis la passer à Windows.
Beaucoup de ces problèmes surviennent à partir de C/C++ étant généralement encodage agnostique.
char
n'est pas vraiment un personnage, c'est juste un type intégral. Même en utilisantchar
des tableaux pour stocker des données UTF-8 peut vous causer des ennuis si vous avez besoin d'accéder aux unités de code, commechar
'signé-ness est pas défini par les normes. Un énoncé commestr[x] < 0x80
à vérifier plusieurs octets caractères peuvent présenter rapidement un bug. (Cette affirmation est toujours vraie sichar
est signé.) UTF-8 code de l'unité est un unsigned type intégral avec une plage de 0 à 255. Qui correspond à la C type deuint8_t
exactement, bien queunsigned char
fonctionne aussi bien. Idéalement ensuite, je ferais une chaîne UTF-8 un tableau deuint8_t
s, mais en raison de l'ancienne Api, ce qui est rarement fait.Certaines personnes ont recommandé
wchar_t
prétendant qu'il s'agit "d'Un caractère Unicode type" ou quelque chose comme ça. Encore une fois, ici, la norme est juste comme un agnostique comme avant, comme C est destinée à travailler n'importe où, et n'importe où peut-être pas à l'aide d'Unicode. Ainsi,wchar_t
n'est pas plus Unicode quechar
. La norme précise:Dans Linux, un
wchat_t
représente un code UTF-32 /unité de point de code. C'est donc 4 octets. Toutefois, dans Windows, c'est un code UTF-16 de l'unité, et est à seulement 2 octets. (Qui, je l'ai dit, n'est pas conforme à ce qui précède, depuis 2 octets ne peut pas représenter l'ensemble de l'Unicode, mais c'est la façon dont il fonctionne.) Cette différence de taille, et de la différence dans l'encodage des données, met clairement une contrainte sur la portabilité. Le standard Unicode se recommande à l'encontre dewchar_t
si vous avez besoin de portabilité. (§5.2)La fin de la leçon: je trouve qu'il est plus facile de stocker toutes mes données dans certaines déclaré format. (Typiquement de l'UTF-8, généralement en std::string, mais je voudrais vraiment quelque chose de mieux.) L'important ici n'est pas de l'UTF-8, mais plutôt, je savoir que mes chaînes de caractères UTF-8. Si je suis de passage à une autre API, il faut aussi que je savoir que cette API s'attend à des chaînes UTF-8. Si ça ne marche pas, alors je dois les convertir. (Donc, si je parle à la Fenêtre de l'API, je dois convertir des chaînes UTF-16). UTF-8 chaîne de texte est un "orange", et un "latin1" chaîne de texte est un "apple". Un
char
tableau qui ne sait pas ce que l'encodage est en est une recette pour un désastre.Mettre UTF-8 points de code dans un
std::string
doit être fine indépendamment de la plateforme. Le problème sur Windows, c'est que presque rien d'autre attend ou travaille avec UTF-8 -- il attend et fonctionne avec UTF-16 à la place. Vous pouvez passer à unstd::wstring
qui permet de stocker de l'UTF-16 (au moins sur la plupart des compilateurs pour Windows) ou vous pouvez écrire d'autres routines qui va accepter de l'UTF-8 (sans doute par la conversion en UTF-16, et de passer ensuite à l'OS).Avez-vous regardé
std::wstring
? C'est une version destd::basic_string
pourwchar_t
plutôt que de lachar
questd::string
utilise.Non, il n'y a aucun moyen de faire de Windows traiter "étroit" chaînes de caractères en UTF-8.
Ici est ce qui fonctionne le mieux pour moi dans cette situation (application multiplate-forme qui a Windows et les versions de Linux).
D'autres approches que j'ai essayé, mais n'aime pas beaucoup:
typedef std::basic_string<TCHAR> tstring;
ensuite utiliser tstring dans le code de commerce. Wrappers/surcharges peut être fait pour simplifier la conversion entre les std::string et std::tstring, mais il ajoute encore beaucoup de douleur.std::wstring
partout. N'aide pas beaucoup depuiswchar_t
est de 16 bits sur Windows, donc vous devez vous limiter à BMP ou aller à beaucoup de complications pour rendre le code de traiter avec Unicode de la croix-plate-forme. Dans ce dernier cas, tous les avantages sur UTF-8 s'évaporer.CString
dans le platfrom partie spécifique; l'utilisationstd::string
dans les platfrom partie. C'est en fait une variante de ce que je vous recommande ci-dessus.CString
est dans de nombreux aspects supérieurs àstd::string
(à mon avis). Mais il introduit un supplément de dépendance et ne sont donc pas toujours acceptable ou pratique.Si vous voulez éviter les maux de tête, de ne pas utiliser la STL types de chaînes. C++ ne sait rien sur Unicode ou de codage, de sorte à être portable, il est préférable d'utiliser une bibliothèque qui est adapté pour le support de l'Unicode, par exemple, l'unité de soins intensifs de la bibliothèque. Soins intensifs utilise l'UTF-16 chaînes par défaut, si aucune conversion n'est nécessaire, et prend en charge les conversions de nombreux autres encodages comme de l'UTF-8. Aussi, essayez de croix-plate-forme de bibliothèques comme Boost.Système de fichiers pour des choses comme le chemin de manipulations (
boost::wpath
). Éviterstd::string
etstd::fstream
.Dans l'API Windows et microsoft C runtime library,
char*
paramètres sont interprétés comme étant codé en "ANSI" page de code. Le problème est que UTF-8 n'est pas pris en charge comme une page de codes ANSIqui Je trouve incroyablement ennuyeux.Je suis dans une situation similaire, étant dans le milieu de portage de logiciels à partir de Windows à Linux tout en le rendant compatible avec Unicode. L'approche que nous avons adoptée est la suivante:
C'est aussi l'approche Poco a pris.
Il vraiment plate-forme de charge, l'Unicode des maux de tête. Dépend du compilateur que vous utilisez. Pour les plus âgés, à partir de MS (VS2010 ou plus), vous devrez utiliser l'API décrite dans MSDN
pour VS2015
selon leurs docs. Je ne peux pas vérifier.
pour mingw, gcc, etc.
de sortie contient le nom de fichier approprié...