web-dev-qa-db-fra.com

Conversion de std :: string "normal" en utf-8

Voyons voir si je peux expliquer cela sans trop d'erreurs factuelles ...

J'écris une classe de chaînes et je veux qu'elle utilise utf-8 (stocké dans une chaîne std ::) car il s'agit du stockage interne. Je veux qu'il puisse prendre les deux "normaux" std::string et std::wstring comme entrée et sortie.

Travailler avec std :: wstring n'est pas un problème, je peux utiliser std::codecvt_utf8<wchar_t> pour convertir à la fois de et vers std :: wstring.

Cependant, après une recherche approfondie sur google et une recherche sur SO je n'ai pas encore trouvé de moyen de convertir entre une chaîne std :: C++ "normale/par défaut" (que je suppose dans Windows utilise la localisation du système local) ?) et une chaîne std :: utf-8.

Je suppose qu'une option serait de convertir d'abord la chaîne std :: en une chaîne std :: wstring en utilisant std::codecvt<wchar_t, char> puis le convertir en utf-8 comme ci-dessus, mais cela semble assez inefficace étant donné qu'au moins les 128 premières valeurs d'un caractère devraient se traduire directement en utf-8 sans conversion quelle que soit la localisation si je comprends bien.

J'ai trouvé cette question similaire: C++: comment convertir ASCII ou ANSI en UTF8 et stocke dans std :: string Bien que je sois un peu sceptique envers cette réponse comme il est codé en dur en latin 1 et je veux que cela fonctionne avec tous les types de localisation pour être sûr.

Aucune réponse impliquant un boost merci, je ne veux pas le mal de tête pour faire fonctionner ma base de code.

15
DaedalusAlpha

Si votre "chaîne normale" est encodée à l'aide de la page de codes du système et que vous souhaitez la convertir en UTF-8, cela devrait fonctionner:

std::string codepage_str;
int size = MultiByteToWideChar(CP_ACP, MB_COMPOSITE, codepage_str.c_str(),
                               codepage_str.length(), nullptr, 0);
std::wstring utf16_str(size, '\0');
MultiByteToWideChar(CP_ACP, MB_COMPOSITE, codepage_str.c_str(),
                    codepage_str.length(), &utf16_str[0], size);

int utf8_size = WideCharToMultiByte(CP_UTF8, 0, utf16_str.c_str(),
                                    utf16_str.length(), nullptr, 0,
                                    nullptr, nullptr);
std::string utf8_str(utf8_size, '\0');
WideCharToMultiByte(CP_UTF8, 0, utf16_str.c_str(),
                    utf16_str.length(), &utf8_str[0], utf8_size,
                    nullptr, nullptr);
18
Simple