Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Jak używać znaków UTF8 w projekcie DEFAULT c++ LUB podczas używania konektora mysql dla c++ w Visual Studio 2019 (Latin7_general_ci do UTF-8)?

Myślę, że problem w twoim przypadku nie jest związany z std::wstring :8-bitowy std::string powinno wystarczyć dla UTF-8 (tworzenie prostego std::string ze znakami specjalnymi "āàčīēļš" po prostu działa dobrze), podczas gdy w zależności od systemu operacyjnego std::wstring ma 2 bajty (Windows) lub 4 bajty (Linux) (więcej informacji tutaj i tutaj ). W końcu, jeśli spojrzysz na getString zobaczysz, że pobiera i zwraca sql::SQLString . sql::SQLString klasa jest prostym opakowaniem dla std::string .

Myślę, że musisz określić utf-8 jako domyślny zestaw znaków dla MySql :W tym celu musisz określić następujące opcje połączenia podczas łączenia się z bazą danych:

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() << ").";
}

Powinno być możliwe kontynuowanie przeszukiwania bazy danych w następujący sposób

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;
}

Problem, który teraz pojawia się, gdy chcesz tworzyć nazwy plików za jego pomocą lub wyprowadzać je do konsoli, to Windows sam (testowałem kod wcześniej tylko z Linuksem i dlatego wcześniej nie napotkałem tego problemu!):Domyślnie używa ANSI, a nie UTF-8. Nawet jeśli wypiszesz coś takiego jak āàčīēļš nie wyświetli go poprawnie bez względu na to, czy używasz std::cout lub std::wcout w połączeniu z std::wstring . Zamiast tego wypisze ─ü├á─ì─½─ô─╝┼í .

Jeśli wyodrębnisz bajty

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;
}

wyświetli C4 81 C3 A0 C4 8D C4 AB C4 93 C4 BC C5 A1 który podłącza go z powrotem do konwertera bajt-do-utf8, takiego jak ten w rzeczywistości da ci āàčīēļš . Tak więc ciąg został odczytany poprawnie, ale Windows po prostu nie wyświetla go poprawnie. Poniższe w połączeniu z ostatnią sekcją (określającą utf-8 jako domyślny zestaw znaków w MySql) powinien naprawić wszystkie twoje problemy:

  • Wywołanie SetConsoleOutputCP(CP_UTF8); z windows.h na początku programu naprawi wyjście konsoli :

     #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;
     }
    
  • Podobnie będziesz musiał dostosować swoją rutynę, która tworzy pliki ponieważ domyślnie nie będzie to również UTF8 (zawartość plików nie będzie problemem, ale sama nazwa pliku będzie!). Użyj std::ofstream z fstream w połączeniu z std::filesystem::u8path z biblioteki C++17 filesystem aby rozwiązać ten problem:

     #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;
     }
    


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Sortowanie według jakiejś kolumny, a także według rand() w MySQL

  2. Neo4j - Utwórz związek za pomocą Cypher

  3. Interfejs zapytań w Railsach, gdzie występuje problem z klauzulą?

  4. Czy użycie magic_quotes() wpływa na użycie mysql_real_escape_string()

  5. Formularz PHP session_start():Nie można wysłać ogranicznika pamięci podręcznej sesji