Saya pikir masalah dalam kasus Anda tidak terkait dengan std::wstring
:std::string
8-bit harus cukup untuk UTF-8 (membuat std::string
simple sederhana dengan karakter khusus "āàčīēļš"
hanya berfungsi dengan baik), sementara tergantung pada sistem operasi std::wstring
adalah 2 Byte (Windows) atau 4 Byte (Linux) (informasi lebih lanjut di sini
dan di sini
). Lagi pula jika Anda melihat getString
fungsi Anda akan melihat bahwa dibutuhkan dan mengembalikan sql::SQLString
. sql::SQLString
class hanyalah pembungkus sederhana untuk std::string
.
Saya pikir Anda harus menentukan utf-8
sebagai set karakter default untuk MySql :Untuk ini, Anda harus menentukan opsi koneksi berikut
saat menghubungkan ke basis data:
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() << ").";
}
Maka Anda harus dapat melanjutkan kueri basis data Anda sebagai berikut
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;
}
Masalah yang sekarang muncul ketika Anda ingin membuat nama file dengannya atau mengeluarkannya ke konsol adalah Windows sendiri (saya telah menguji kode sebelumnya hanya dengan Linux dan oleh karena itu tidak mengalami masalah ini sebelumnya!):Secara default ia menggunakan ANSI dan bukan UTF-8. Bahkan jika Anda menampilkan sesuatu seperti āàčīēļš
itu tidak akan menampilkannya dengan benar tidak peduli jika Anda menggunakan std::cout
atau std::wcout
dalam kombinasi dengan std::wstring
. Sebaliknya itu akan menampilkan āàčīēļš
.
Jika Anda mengekstrak byte
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;
}
itu akan menampilkan C4 81 C3 A0 C4 8D C4 AB C4 93 C4 BC C5 A1
yang menghubungkannya kembali ke byte-to-utf8-converter seperti yang ini
sebenarnya akan memberi Anda āàčīēļš
. Jadi string dibaca dengan benar tetapi Windows tidak menampilkannya dengan benar. Berikut ini dalam kombinasi dengan bagian terakhir (menentukan utf-8
sebagai set karakter default di MySql) akan memperbaiki semua masalah Anda:
-
Panggilan ke
SetConsoleOutputCP(CP_UTF8);
dariwindows.h
di awal program akan memperbaiki output konsol :#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; }
-
Demikian pula, Anda harus menyesuaikan rutinitas Anda yang membuat file karena secara default juga tidak akan menjadi UTF8 (Isi file tidak akan menjadi masalah tetapi nama file itu sendiri akan menjadi masalah!). Gunakan
std::ofstream
darifstream
dalam kombinasi denganstd::filesystem::u8path
dari pustaka C++17filesystem
untuk mengatasi ini:#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; }