Tôi nghĩ rằng vấn đề trong trường hợp của bạn không liên quan đến std::wstring
:std::string
8 bit phải đủ cho UTF-8 (tạo một std::string
đơn giản với các ký tự đặc biệt "āàčīēļš"
chỉ hoạt động tốt), trong khi tùy thuộc vào hệ điều hành std::wstring
là 2 Byte (Windows) hoặc 4 Byte (Linux) (thêm thông tin tại đây
và tại đây
). Sau tất cả, nếu bạn đã xem getString
bạn sẽ thấy rằng nó nhận và trả về một sql::SQLString
. sql::SQLString
lớp chỉ là một trình bao bọc đơn giản cho một std::string
.
Tôi nghĩ bạn phải chỉ định utf-8
làm ký tự mặc định được đặt cho MySql :Đối với điều này, bạn sẽ phải chỉ định các tùy chọn kết nối sau
khi kết nối với cơ sở dữ liệu:
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() << ").";
}
Sau đó, bạn sẽ có thể tiếp tục truy vấn cơ sở dữ liệu của mình như sau
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;
}
Sự cố bây giờ xuất hiện khi bạn muốn tạo tên tệp với nó hoặc xuất nó ra bảng điều khiển là Windows (Tôi đã thử nghiệm mã trước đây chỉ với Linux và do đó không gặp phải vấn đề này trước đây!):Theo mặc định, nó sử dụng ANSI chứ không phải UTF-8. Ngay cả khi bạn xuất một cái gì đó như āàčīēļš
nó sẽ không xuất ra chính xác cho dù bạn đang sử dụng std::cout
hoặc std::wcout
kết hợp với std::wstring
. Thay vào đó, nó sẽ xuất ra ─ü├á─ì─½─ô─╝┼í
.
Nếu bạn trích xuất các 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;
}
nó sẽ xuất ra C4 81 C3 A0 C4 8D C4 AB C4 93 C4 BC C5 A1
cắm lại nó vào bộ chuyển đổi byte-to-utf8, chẳng hạn như cái này
thực tế sẽ cung cấp cho bạn āàčīēļš
. Vì vậy, chuỗi đã được đọc chính xác nhưng Windows không hiển thị chính xác. Phần sau kết hợp với phần cuối cùng (chỉ định utf-8
làm ký tự mặc định được đặt trong MySql) sẽ khắc phục tất cả các vấn đề của bạn:
-
Lệnh gọi đến
SetConsoleOutputCP(CP_UTF8);
từwindows.h
khi bắt đầu chương trình sẽ sửa đầu ra bảng điều khiển :#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; }
-
Tương tự, bạn sẽ phải điều chỉnh quy trình tạo tệp theo mặc định, nó cũng sẽ không phải là UTF8 (Nội dung của các tệp sẽ không phải là vấn đề nhưng chính tên tệp sẽ có!). Sử dụng
std::ofstream
từfstream
kết hợp vớistd::filesystem::u8path
từ thư viện C ++ 17filesystem
để giải quyết vấn đề này:#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; }