Je pense que le problème dans votre cas n'est pas lié à std::wstring
:le std::string
8 bits devrait être suffisant pour UTF-8 (créer un simple std::string
avec les caractères spéciaux "āàčīēļš"
fonctionne très bien), tout en dépendant du système d'exploitation std::wstring
est de 2 octets (Windows) ou de 4 octets (Linux) (plus d'informations ici
et ici
). Après tout, si vous regardez le getString
vous verrez qu'elle prend et renvoie un sql::SQLString
. Le sql::SQLString
la classe est juste un simple wrapper pour un std::string
.
Je pense que vous devez spécifier utf-8
comme jeu de caractères par défaut pour MySql :Pour cela vous devrez spécifier le options de connexion suivantes
lors de la connexion à la base de données :
std::unique_ptr<sql::Connection> connection {nullptr};
try {
sql::Driver* driver = ::get_driver_instance();
sql::ConnectOptionsMap connection_options {};
connection_options["hostName"] = url; // Replace with your log-in
connection_options["userName"] = username; // ...
connection_options["password"] = password; // ...
connection_options["schema"] = schema; // ...
connection_options["characterSetResults"] = "utf8";
connection_options["OPT_CHARSET_NAME"] = "utf8";
connection_options["OPT_SET_CHARSET_NAME"] = "utf8";
connection.reset(driver->connect(connection_options));
} catch (sql::SQLException& ex) {
std::cerr << "Error occured when connecting to SQL data base: " << ex.what() << "(" << ex.getErrorCode() << ").";
}
Ensuite, vous devriez pouvoir continuer à interroger votre base de données comme suit
std::string const some_query = "SELECT * FROM some_table_name;";
std::unique_ptr<sql::Statement> statement {connection->createStatement()};
std::unique_ptr<sql::ResultSet> result {statement->executeQuery(some_query)};
while (result->next()) {
std::string const some_field = result->getString("some_field_name");
// Process: e.g. display with std::cout << some_field << std::endl;
}
Le problème qui apparaît maintenant lorsque vous souhaitez créer des noms de fichiers avec ou les sortir sur la console est Windows lui-même (j'avais testé le code auparavant avec Linux uniquement et je n'avais donc pas rencontré ce problème auparavant !) :par défaut, il utilise ANSI et non UTF-8. Même si vous affichez quelque chose comme āàčīēļš
il ne le sortira pas correctement, peu importe si vous utilisez un std::cout
ou std::wcout
en combinaison avec std::wstring
. Au lieu de cela, il affichera āàčīēļš
.
Si vous extrayez les octets
void dump_bytes(std::string const& str) {
std::cout << std::hex << std::uppercase << std::setfill('0');
for (unsigned char c : str) {
std::cout << std::setw(2) << static_cast<int>(c) << ' ';
}
std::cout << std::dec << std::endl;
return;
}
il affichera C4 81 C3 A0 C4 8D C4 AB C4 93 C4 BC C5 A1
qui le rebranche dans un convertisseur octet en utf8 tel que celui-ci
vous donnera en fait āàčīēļš
. La chaîne a donc été lue correctement, mais Windows ne l'affiche tout simplement pas correctement. Ce qui suit en combinaison avec la dernière section (en spécifiant utf-8
comme jeu de caractères par défaut dans MySql) devrait résoudre tous vos problèmes :
-
Un appel à
SetConsoleOutputCP(CP_UTF8);
depuiswindows.h
au début du programme corrigera la sortie de la console :#include <cstdlib> #include <iostream> #include <string> #include <windows.h> int main() { // Forces console output to UTF8 SetConsoleOutputCP(CP_UTF8); std::string const name = u8"āàčīēļš"; std::cout << name << std::endl; // Actually outputs āàčīēļš return EXIT_SUCCESS; }
-
De même vous devrez adapter votre routine qui crée les fichiers car par défaut, ce ne sera pas non plus UTF8 (le contenu des fichiers ne sera pas un problème mais le nom de fichier lui-même le sera !). Utilisez
std::ofstream
depuisfstream
en combinaison avecstd::filesystem::u8path
de la bibliothèque C++17filesystem
pour résoudre ce problème :#include <cstdlib> #include <filesystem> #include <fstream> #include <string> int main() { std::string const name = u8"āàčīēļš"; std::ofstream f(std::filesystem::u8path(name + ".txt")); // Creates a file āàčīēļš.txt f << name << std::endl; // Writes āàčīēļš to it return EXIT_SUCCESS; }