Jeg tror, at problemet i dit tilfælde ikke er relateret til std::wstring
:8-bit std::string
burde være tilstrækkeligt til UTF-8 (opretter en simpel std::string
med specialtegnene "āàčīēļš"
fungerer bare fint), mens det afhænger af operativsystemet std::wstring
er 2 Byte (Windows) eller 4 Byte (Linux) (mere information her
og her
). Når alt kommer til alt, hvis du har et kig på getString
funktion vil du se, at den tager og returnerer en sql::SQLString
. sql::SQLString
klasse er blot en simpel indpakning for en std::string
.
Jeg tror, du skal specificere utf-8
som standardtegnsæt for MySql :Til dette skal du angive følgende tilslutningsmuligheder
ved tilslutning til databasen:
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() << ").";
}
Så skulle du kunne fortsætte med at forespørge i din database som følger
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;
}
Problemet, der nu dukker op, når du vil oprette filnavne med det eller udlæse det til konsollen, er Windows selv (jeg havde kun testet koden før med Linux og stødte derfor ikke på dette problem før!):Som standard bruger den ANSI og ikke UTF-8. Selv hvis du udsender noget som āàčīēļš
det vil ikke udlæse det korrekt, uanset om du bruger en std::cout
eller std::wcout
i kombination med std::wstring
. I stedet vil den udsende āàčīēļš
.
Hvis du udpakker bytes
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;
}
den udsender C4 81 C3 A0 C4 8D C4 AB C4 93 C4 BC C5 A1
som sætter den tilbage i en byte-til-utf8-konverter, såsom denne
vil faktisk give dig āàčīēļš
. Så strengen blev læst korrekt, men Windows viser den bare ikke korrekt. Det følgende i kombination med det sidste afsnit (angiver utf-8
som standardtegnsæt i MySql) skulle løse alle dine problemer:
-
Et kald til
SetConsoleOutputCP(CP_UTF8);
frawindows.h
i starten af programmet vil rette konsoloutputtet :#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; }
-
På samme måde bliver du nødt til at tilpasse din rutine, der opretter filerne da det som standard ikke også vil være UTF8 (indholdet af filerne vil ikke være et problem, men selve filnavnet vil være det!). Brug
std::ofstream
frafstream
i kombination medstd::filesystem::u8path
fra C++17-biblioteketfilesystem
for at løse dette:#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; }