Ich denke, das Problem in Ihrem Fall hängt nicht mit std::wstring
zusammen :der 8-Bit std::string
sollte für UTF-8 ausreichen (Erstellen eines einfachen std::string
mit den Sonderzeichen "āàčīēļš"
funktioniert einfach gut), während je nach Betriebssystem std::wstring
ist 2 Byte (Windows) oder 4 Byte (Linux) (weitere Informationen hier
). und hier
). Immerhin, wenn Sie sich den getString
ansehen Funktion sehen Sie, dass sie einen sql::SQLString
nimmt und zurückgibt . Der sql::SQLString
class ist nur ein einfacher Wrapper für einen std::string
.
Ich denke, Sie müssen utf-8
angeben als Standardzeichensatz für MySql :Dazu müssen Sie folgende Verbindungsoptionen
beim Verbinden mit der Datenbank:
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() << ").";
}
Dann sollten Sie Ihre Datenbank wie folgt weiter abfragen können
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;
}
Das Problem, das nun auftaucht, wenn man damit Dateinamen erstellen oder auf die Konsole ausgeben will, ist Windows selbst (Ich hatte den Code zuvor nur mit Linux getestet und bin daher vorher nicht auf dieses Problem gestoßen!):Standardmäßig verwendet es ANSI und nicht UTF-8. Auch wenn Sie so etwas wie āàčīēļš
ausgeben es wird es nicht korrekt ausgeben, egal ob Sie einen std::cout
verwenden oder std::wcout
in Kombination mit std::wstring
. Stattdessen wird āàčīēļš
ausgegeben .
Wenn Sie die Bytes extrahieren
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;
}
es wird C4 81 C3 A0 C4 8D C4 AB C4 93 C4 BC C5 A1
ausgegeben die es wieder in einen Byte-zu-utf8-Konverter wie diesen
einstecken wird Ihnen tatsächlich āàčīēļš
geben . Die Zeichenfolge wurde also korrekt gelesen, aber Windows zeigt sie einfach nicht korrekt an. Das Folgende in Kombination mit dem letzten Abschnitt (Angabe von utf-8
als Standardzeichensatz in MySql) sollte alle Ihre Probleme beheben:
-
Ein Aufruf von
SetConsoleOutputCP(CP_UTF8);
auswindows.h
beim Start des Programms korrigiert die Konsolenausgabe :#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; }
-
Ebenso müssen Sie Ihre Routine anpassen, die die Dateien erstellt da es standardmäßig auch nicht UTF8 sein wird (Der Inhalt der Dateien wird kein Problem sein, aber der Dateiname selbst wird es sein!). Verwenden Sie
std::ofstream
vonfstream
in Kombination mitstd::filesystem::u8path
aus der C++17-Bibliothekfilesystem
um dies zu beheben:#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; }