如何在默认 c++ 项目中使用 UTF8 字符或在 Visual Studio 2019Latin7_general_ci to UTF-8中使用 c++ 的 mysql 连接器时?

问题描述

SEEMS LIKE latin1 ISO-8859-1 甚至不能保存特殊字符,所以数据库的格式必须是 Latin7 ISO-8859-7。真的找不到简单的函数来做到这一点,我真的必须自己写一个吗?

更新,更新 --- 我在这篇问题文章中描述的小进步 - Special characters in Visual Studio 2019 C++ project AND executing CMD commands with them

但问题似乎出现在没有任何 MysqL 库或任何东西的认项目设置上,在所有正确的编码文件中。 (UTF8) 即使添加了编译标志,即使安装了“修复文件编码”。

db.collection.aggregate([
  {
    $project: {
      time: {
        "$datetoString": {
          "date": {
            "$dateFromString": {
              "dateString": "$time","format": "%Y-%m-%dT%H"
            }
          },"format": "%Hh %d.%m.%Y"
        }
      }
    }
  }
])

Intro rant* - 这是关于 MysqL Connector 的第 3 篇文章,因为我根本无法在 Google 中找到有关 MysqL Connector 的基本信息(MySQL and MariaDB library's in C++ using cmake,mingw),首先没有解释 GCC 将无法为 Windows 系统编译它,然后我没有找到如何在数据库输出中使用 datetime 和 int 对象,直到我在这里发布问题 (How to return time,date data fields in c++ mysql oracle vs17?)。

我现在的问题是从数据库返回的字符串具有特殊字符 - āàčīēļš 等。 列:test2col 校对:Latin7_general_ci

所以这是可能工作的代码,但不是由于表格或错误,任何专业知识都可能有所帮助:

#include <iostream>
int main() {
    string output = "āāāčččēēēē";

    cout << output << endl;
}
#include <iostream>
#include <string>
#include <string_view>

std::string_view itou[256] {
{"\x00",1},{"\x01",{"\x02",{"\x03",{"\x04",{"\x05",{"\x06",{"\x07",{"\x08",{"\x09",{"\x0a",{"\x0b",{"\x0c",{"\x0d",{"\x0e",{"\x0f",{"\x10",{"\x11",{"\x12",{"\x13",{"\x14",{"\x15",{"\x16",{"\x17",{"\x18",{"\x19",{"\x1a",{"\x1b",{"\x1c",{"\x1d",{"\x1e",{"\x1f",{"\x20",{"\x21",{"\x22",{"\x23",{"\x24",{"\x25",{"\x26",{"\x27",{"\x28",{"\x29",{"\x2a",{"\x2b",{"\x2c",{"\x2d",{"\x2e",{"\x2f",{"\x30",{"\x31",{"\x32",{"\x33",{"\x34",{"\x35",{"\x36",{"\x37",{"\x38",{"\x39",{"\x3a",{"\x3b",{"\x3c",{"\x3d",{"\x3e",{"\x3f",{"\x40",{"\x41",{"\x42",{"\x43",{"\x44",{"\x45",{"\x46",{"\x47",{"\x48",{"\x49",{"\x4a",{"\x4b",{"\x4c",{"\x4d",{"\x4e",{"\x4f",{"\x50",{"\x51",{"\x52",{"\x53",{"\x54",{"\x55",{"\x56",{"\x57",{"\x58",{"\x59",{"\x5a",{"\x5b",{"\x5c",{"\x5d",{"\x5e",{"\x5f",{"\x60",{"\x61",{"\x62",{"\x63",{"\x64",{"\x65",{"\x66",{"\x67",{"\x68",{"\x69",{"\x6a",{"\x6b",{"\x6c",{"\x6d",{"\x6e",{"\x6f",{"\x70",{"\x71",{"\x72",{"\x73",{"\x74",{"\x75",{"\x76",{"\x77",{"\x78",{"\x79",{"\x7a",{"\x7b",{"\x7c",{"\x7d",{"\x7e",{"\x7f",{"\xc2""\x80",2},{"\xc2""\x81",{"\xc2""\x82",{"\xc2""\x83",{"\xc2""\x84",{"\xc2""\x85",{"\xc2""\x86",{"\xc2""\x87",{"\xc2""\x88",{"\xc2""\x89",{"\xc2""\x8a",{"\xc2""\x8b",{"\xc2""\x8c",{"\xc2""\x8d",{"\xc2""\x8e",{"\xc2""\x8f",{"\xc2""\x90",{"\xc2""\x91",{"\xc2""\x92",{"\xc2""\x93",{"\xc2""\x94",{"\xc2""\x95",{"\xc2""\x96",{"\xc2""\x97",{"\xc2""\x98",{"\xc2""\x99",{"\xc2""\x9a",{"\xc2""\x9b",{"\xc2""\x9c",{"\xc2""\x9d",{"\xc2""\x9e",{"\xc2""\x9f",{"\xc2""\xa0",{"\xe2""\x80""\x98",3},{"\xe2""\x80""\x99",{"\xc2""\xa3",{"\xe2""\x82""\xac",{"\xe2""\x82""\xaf",{"\xc2""\xa6",{"\xc2""\xa7",{"\xc2""\xa8",{"\xc2""\xa9",{"\xcd""\xba",{"\xc2""\xab",{"\xc2""\xac",{"\xc2""\xad",{"\xe2""\x80""\x95",{"\xc2""\xb0",{"\xc2""\xb1",{"\xc2""\xb2",{"\xc2""\xb3",{"\xce""\x84",{"\xce""\x85",{"\xce""\x86",{"\xc2""\xb7",{"\xce""\x88",{"\xce""\x89",{"\xce""\x8a",{"\xc2""\xbb",{"\xce""\x8c",{"\xc2""\xbd",{"\xce""\x8e",{"\xce""\x8f",{"\xce""\x90",{"\xce""\x91",{"\xce""\x92",{"\xce""\x93",{"\xce""\x94",{"\xce""\x95",{"\xce""\x96",{"\xce""\x97",{"\xce""\x98",{"\xce""\x99",{"\xce""\x9a",{"\xce""\x9b",{"\xce""\x9c",{"\xce""\x9d",{"\xce""\x9e",{"\xce""\x9f",{"\xce""\xa0",{"\xce""\xa1",{"\xce""\xa3",{"\xce""\xa4",{"\xce""\xa5",{"\xce""\xa6",{"\xce""\xa7",{"\xce""\xa8",{"\xce""\xa9",{"\xce""\xaa",{"\xce""\xab",{"\xce""\xac",{"\xce""\xad",{"\xce""\xae",{"\xce""\xaf",{"\xce""\xb0",{"\xce""\xb1",{"\xce""\xb2",{"\xce""\xb3",{"\xce""\xb4",{"\xce""\xb5",{"\xce""\xb6",{"\xce""\xb7",{"\xce""\xb8",{"\xce""\xb9",{"\xce""\xba",{"\xce""\xbb",{"\xce""\xbc",{"\xce""\xbd",{"\xce""\xbe",{"\xce""\xbf",{"\xcf""\x80",{"\xcf""\x81",{"\xcf""\x82",{"\xcf""\x83",{"\xcf""\x84",{"\xcf""\x85",{"\xcf""\x86",{"\xcf""\x87",{"\xcf""\x88",{"\xcf""\x89",{"\xcf""\x8a",{"\xcf""\x8b",{"\xcf""\x8c",{"\xcf""\x8d",{"\xcf""\x8e",1}
};

int main() {
    std::string input{"āāāčččēēēē"};
    std::string output;
    for (auto c : input) {
        output.append(itou[static_cast<uint8_t>(c)]);
    }

    std::cout << output << std::endl;
}

MysqL 连接器的文档:https://dev.MysqL.com/doc/dev/connector-cpp/8.0/

似乎不太了解这个,所以感谢您的帮助!

所以这里的代码示例根据注释中的解决方案变成另一个错误 -

string FirstName = res->getString("test2col");
157

#include <iostream>
 #include <cppconn/driver.h> 
#include <cppconn/exception.h>
 #include <cppconn/resultset.h>
 #include <cppconn/statement.h> 
#include <cppconn/prepared_statement.h> 
#include <string>
 #include <fstream>
 #include <sstream> 
#include <stdexcept>
 #include <stdlib.h> 
#include <stdio.h> 
#include <time.h> 
#include <cstring> 
#include <filesystem>
 #include <codecvt> 
#include <cstdint>
 #include <locale> 

Severity    Code    Description Project File    Line    Suppression State Error C4996   'std::wstring_convert<std::codecvt_utf8<wchar_t,1114111,(std::codecvt_mode)0>,wchar_t,std::allocator<wchar_t>,std::allocator<char>>::to_bytes': warning STL4017: std::wbuffer_convert,std::wstring_convert,and the <codecvt> header (containing std::codecvt_mode,std::codecvt_utf8,std::codecvt_utf16,and std::codecvt_utf8_utf16) are deprecated in C++17. (The std::codecvt class template is NOT deprecated.) The C++ Standard doesn't provide equivalent non-deprecated functionality; consider using MultiBytetoWideChar() and WideCharToMultiByte() from <Windows.h> instead. You can define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to ackNowledge that you have received this warning.   

```cpp
     try
            {
                std::unique_ptr<sql::Connection> connection{ nullptr };
                try {
                    sql::Driver* driver = ::get_driver_instance();

                    //sql::Connection* con;
                    //sql::Statement *stmt;
                    //sql::ResultSet* res;
                    //sql::Statement* pstmt;

                    sql::ConnectOptionsMap connection_options{};
                    connection_options["hostName"] = "tcp://127.0.0.1:3306";      // Replace with your log-in
                    connection_options["userName"] = "root"; // ...
                    connection_options["password"] = "parole123!"; // ...
                    connection_options["schema"] = "test";     // ...
                    connection_options["characterSetResults"] = "latin7_general_ci";
                    connection_options["OPT_CHARSET_NAME"] = "latin7_general_ci";
                    connection_options["OPT_SET_CHARSET_NAME"] = "latin7_general_ci";

                    connection.reset(driver->connect(connection_options));
                    driver = get_driver_instance();


                    /* Create a connection */

                    //con = driver->connect("tcp://127.0.0.1:3306","root","parole123!");
                    //con->setClientOption("characterSetResults","UTF8");

                    /* Connect to the MysqL test database */
                    //con->setSchema("test");
                    //pstmt = con->createStatement();
                    std::string const some_query = "SELECT * FROM test2";

                    std::unique_ptr<sql::Statement> statement{ connection->createStatement() };


                    //res = pstmt->executeQuery("SELECT * FROM test2");
                    std::unique_ptr<sql::ResultSet> res{ statement->executeQuery(some_query) };

                    //pstmt->setInt(1,1);
                    //pstmt->setString(1,str2);
                    //res = pstmt->executeQuery();

                    /* Fetch in reverse = descending order! */

                    ///cikls kur izmantos MysqL datu masvu
                    //res->afterLast();
                    while (res->next()) {
                        std::string const FILE_NAME = res->getString("test2col");
    



                        string locations2 = ("C:\\Users\\Janis\\Desktop\\TEST2\\");
                        string txtt = (".txt");
                        string copy2 = ("copy /-y ");

                        string space = " ";
                        string PACIENTI2 = "C:\\PACIENTI\\";




                        string element = copy2 + locations2 + FILE_NAME + txtt;


                        //string StartTime = res->getString("StartTime");
                        //string VisitID = res->getString("VisitID");
                        //string LastModified = res->getString("LastModified");
                        //string Id = res->getString("Id");
                        //string PatientId = res->getString("PatientId");
                        for (auto& p2 : fs::directory_iterator("C:\\Users\\Janis\\Desktop\\TEST2\\")) {
                            if (FILE_NAME != p2.path().string()) {
                                string cmd = element + space + PACIENTI2 + FILE_NAME + txtt;

                                FILE* pipe = _popen(cmd.c_str(),"r");
                                cout << cmd << endl;

                                /*if (pipe == NULL)
                                {
                                    return;
                                }

                                char buffer[128];
                                std::string result = "";

                                while (!feof(pipe))
                                {
                                    if (fgets(buffer,128,pipe) != NULL)
                                    {
                                        result += buffer;
                                    }
                                }*/
                                //std::cout << "Results: " << std::endl << result << std::endl ;

                                //_pclose(pipe);
                            }
                        }


                    }
                    //delete res;
                    //delete pstmt;
                    //delete con;




                }
                catch (sql::sqlException& ex) {
                    std::cerr << "Error occured when connecting to sql data base: " << ex.what() << "(" << ex.getErrorCode() << ").";
                }


            }
            catch (sql::sqlException& e)
            {
                ///nav implementēts vairāk info
                //cout << "# ERR: sqlException in " << __FILE__;
                //cout << "(" << __FUNCTION__ << ") on line " << __LINE__ << endl;
                /* what() (derived from std::runtime_error) fetches error message */
                //cout << "# ERR: " << e.what();
                //cout << " (MysqL error code: " << e.getErrorCode();
                cout << "# ERR: sqlException in " << endl;
            }

应该是

copy /-y C:\Users\username\Desktop\TEST2\J─ünis.txt C:\PACIENTI\J─ünis.txt
copy /-y C:\Users\username\Desktop\TEST2\Ann─ü.txt C:\PACIENTI\Ann─ü.txt

enter image description here

解决方法

我认为您的情况下的问题与 std::wstring 无关:8 位 std::string 对 UTF-8 来说应该足够了(使用特殊字符 { 创建一个简单的 std::string {1}} 工作正常),而取决于操作系统,"āàčīēļš" 是 2 字节 (Windows) 或 4 字节 (Linux)(更多信息 herehere)。毕竟,如果您查看 std::wstring 函数,您会发现它接受并返回一个 getStringsql::SQLString 类只是 sql::SQLString 的简单包装器。

我认为您必须指定 std::string 作为 MySql 的默认字符集:为此,您必须在连接到数据库时指定 following connection options: >

utf-8

然后你应该可以继续查询你的数据库了

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

现在当你想用它创建文件名或将它输出到控制台时出现的问题是 Windows 本身(我之前只用 Linux 测试过代码,因此没有遇到这个问题之前!):默认情况下,它使用 ANSI 而不是 UTF-8。即使您输出类似 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; } 的内容,无论您将 āàčīēļšstd::coutstd::wcout 结合使用,它也不会正确输出。相反,它会输出 std::wstring

如果你提取字节

āàčīēļš

它会输出 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; } ,将它插回一个字节到 utf8 的转换器,例如 this one 实际上会给你 C4 81 C3 A0 C4 8D C4 AB C4 93 C4 BC C5 A1。所以字符串被正确读取,但 Windows 只是没有正确显示它。以下结合最后一部分(在 MySql 中指定 āàčīēļš 作为默认字符集)应该可以解决您的所有问题:

  • 在程序开始时从 utf-8 调用 SetConsoleOutputCP(CP_UTF8); 将修复控制台输出

    windows.h
  • 同样,您必须调整创建文件的例程,因为默认情况下它也不会是 UTF8(文件的内容不是问题,而是文件名本身会!)。将 #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; } 中的 std::ofstream 与 C++17 库 fstream 中的 std::filesystem::u8path 结合使用可解决此问题:

    filesystem
,

为此,您需要将字符串转换为 std::wstring。

#include <codecvt>

string FirstName = res->getString("FirstName");

std::wstring firstNameWstring = std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes(FirstName);

,

问题在于代码的不同部分使用了不同的文本数据编码。

由于 MySql 使用 utf-8,您可以简单地更改您的程序以在任何地方使用 UTF-8。 这可以通过构建标志来实现:

cl /source-charset:utf-8 /execution-charset:utf-8 /EHsc YourSources.cpp
  • /source-charset:utf-8 - 表示您的源文件正在使用 utf-8 编码 - 因为您的源可以使用不同的编码确保您使用正确的参数,但强烈建议源代码以标准编码,即通用(因此为 UTF-8),因此来自不同国家/地区的开发人员可以毫无问题地处理代码。
  • /execution-charset:utf-8 - 表示存储在精确中的字符串文字应编码为 utf-8

现在问题将只是一个控制台 (cmd)。默认情况下,Windows 控制台使用特定于系统语言设置的编码(继承与旧 DOS 应用程序的兼容性)。因此,当您强制您的可执行文件默认使用 utf-8 控制台时,会错误地打印这些内容。

更改控制台的代码页以便使用 utf-8 将解决该问题。

这是我编写的一个测试程序,用于演示如何在 C++ 中处理编码:

#include <iostream>
#include <locale>
#include <exception>
#include <string>

void setupLocale(int argc,const char *argv[])
{
    std::locale def{""};
    std::locale::global(argc > 1 ? std::locale{argv[1]} : def);
    auto streamLocale = argc > 2 ? std::locale{argv[2]} : def;
    std::cout.imbue(streamLocale);
    std::cin.imbue(streamLocale);
}

void printSeparator()
{
    std::cout << "---------\n";
}

void printTestStuff()
{
    std::cout << "Wester Europe: āāāčččēēēēßÞÖöñÅÃ\n";
    std::cout << "Central Europe: ąĄÓóŁłĘężćźŰűÝýĂă\n";
    std::cout << "China: 字集碼是把字符集中的字符编码为指定集合中某一对象\n";
    std::cout << "Korean: 줄여서 인코딩은 사용자가 입력한\n";
}

int main(int argc,const char *argv[]) {
    try{
        setupLocale(argc,argv);
        printSeparator();
        printTestStuff();
        printSeparator();
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << '\n';
    }
}

当您复制粘贴该程序时,请记住以 UTF-8 编码源代码(因为我使用了广泛的字符来测试大多数其他编码将失败 - 打开文件时将无法正确显示)。

现在这是我在终端上看到的(复制粘贴):

C:\Users\User\Downloads>cl /source-charset:utf-8 /execution-charset:utf-8 /EHsc encodings.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29336 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

encodings.cpp
Microsoft (R) Incremental Linker Version 14.28.29336.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:encodings.exe
encodings.obj

C:\Users\User\Downloads>chcp
Active code page: 437

C:\Users\User\Downloads>encodings.exe
---------
Wester Europe: Ä?Ä?Ä?Ä?Ä?Ä?Ä"Ä"Ä"Ä"AYAzA-AA±A.Aƒ
Central Europe: Ä.Ä,A"A3Å?Å,Ä~ÄTżÄ╪źŰűA?A½Ä,ă
China: å--é>+碼æ~_æSSå--ç¬▌é>+ä,-çs,å--ç¬▌ç¼-ç ?ä,ºæO╪årsé>+å?^ä,-æY?ä,?å_1象
Korean: ì,ì-¬ì,o ì?,ì½"ë"cì?? ì,¬ìscìz?ê°? ìz.ë ¥ío
---------

C:\Users\User\Downloads>encodings.exe .65001
---------
Wester Europe: aaaccceeeeß_ÖöñÅA
Central Europe: aAOóLlEezczUuYyAa
China: ????????????????????????
Korean: ??? ???? ???? ???
---------

C:\Users\User\Downloads>encodings.exe .65001 .437
---------
Wester Europe: aaaccceeeeß_ÖöñÅA
Central Europe: aAOóLlEezczUuYyAa
China: ????????????????????????
Korean: ??? ???? ???? ???
---------

C:\Users\User\Downloads>encodings.exe .65001 .1250
---------
Wester Europe: aaaccceeeeß_ÖöñÅA
Central Europe: aAOóLlEezczUuYyAa
China: ????????????????????????
Korean: ??? ???? ???? ???
---------

C:\Users\User\Downloads>chcp 1250
Active code page: 1250

C:\Users\User\Downloads>encodings.exe .65001 .1250
---------
Wester Europe: aaačččeeeeß?ÖönAA
Central Europe: ąĄÓóŁłĘężćźŰűÝýĂă
China: ????????????????????????
Korean: ??? ???? ???? ???
---------

C:\Users\User\Downloads>chcp 65001
Active code page: 65001

C:\Users\User\Downloads>encodings.exe
---------
Wester Europe: ÄÄÄÄÄÄēēēēßÞÖöñÅÃ
Central Europe: ąĄÓóÅłĘężćźŰűÃýĂă
China: 字集碼是把字符集中的字符编ç ä¸ºæŒ‡å®šé›†åˆä¸­æŸä¸€å¯¹è±¡
Korean: 줄여서 ì¸ì½”ë”©ì€ ì‚¬ìš©ìžê°€ 입력한
---------

C:\Users\User\Downloads>encodings.exe .65001
---------
Wester Europe: āāāčččēēēēßÞÖöñÅÃ
Central Europe: ąĄÓóŁłĘężćźŰűÝýĂă
China: 字集碼是把字符集中的字符编码为指定集合中某一对象
Korean: 줄여서 인코딩은 사용자가 입력한
---------

C:\Users\User\Downloads>encodings.exe .65001 .65001
---------
Wester Europe: āāāčččēēēēßÞÖöñÅÃ
Central Europe: ąĄÓóŁłĘężćźŰűÝýĂă
China: 字集碼是把字符集中的字符编码为指定集合中某一对象
Korean: 줄여서 인코딩은 사용자가 입력한
---------

C:\Users\User\Downloads>

如您所见,如果代码页和编码设置正确,一切正常(不使用 Windows API)。

在我的机器上,cmd.exe 无法正确显示亚洲字符,但这只是字体问题,当我将粘贴 cmd.exe 内容复制到其他程序时,一切都显示正确(如果正确设置了编码在我的程序中)。

另请注意,如果无法转换,则会显示问号并执行回退到某个其他字符(例如,当 Å 编码和代码页为 A 时,Windows-1250 已转换为 std::locale::global使用)。

稍微玩一下这个程序,我很确定这应该足以让您全面了解。

最重要:

  • std::string 定义了主程序使用的编码类型。这意味着流假定 std::iostream::imbue 值以这种方式编码
  • import random vec_array = [] for x in range(100): row = [random.randint(0,10),random.randint(0,10)] print(row) vec_array.append(row) print(vec_array) 允许定义流的编码,播种将写入文件的内容。
  • 这两个设置都定义了转换的双方!您不必手动进行转换!
,

C4 81 C3 A0 C4 8D C4 AB C4 93 C4 BC C5 A1,当解释为各种编码时:

utf8:    āàčīēļš
latin1:  Äà Äīēļš
latin7:  ÄĆÄ Ä Ä«ÄļŔ
euckr    훮횪훾카휆캬큄

想必,您想要 utf8(或 utf8mb4)。

connection 参数指定客户端 的编码。如果该十六进制字符串来自客户端,则指定 utf8(或 utf8mb4)。

数据库表中的编码可以相同也可以不同。那是在模式中指定的;例如:

CREATE TABLE ...
    stuff VARCHAR(99) CHARACTER SET utf8
    ...

INSERTingSELECTing时,MySQL将在客户端编码和编码之间进行转换(如有必要)。

发现:

查看客户端设置:

SHOW VARIABLES LIKE 'char%'; 

:--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin7                     | <--
| character_set_connection | latin7                     | <--
| character_set_database   | utf8mb4                    |
| character_set_filesystem | binary                     |
| character_set_results    | latin7                     | <--
| character_set_server     | utf8mb4                    |
| character_set_system     | utf8mb3                    |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+

要查看列的编码:SHOW CREATE TABLE tablename;

要查看列中的实际字节数:

SELECT col,HEX(col) ...

几乎所有其他技术都容易出错。

请注意,您提到的重音字符都具有 UTF-8 十六进制,例如

C3 xx
C4 xx
C5 xx

术语:

“字符集”然后是编码。示例:latin1、latin7、utf8、utf8mb4。

“排序规则”是指如何对值进行排序和比较。示例:latin7_general_ci(“ci”是“不区分大小写和不区分重音”的缩写)

(您的连接参数混淆了字符集和排序规则。)

"utf8" 或 "utf8mb3" 是 MySQL 的 3 字节编码。即将消失,但仍然适用于所有欧洲语言以及世界其他大部分地区。

"utf8mb4" 是 MySQL 的 4 字节编码。相当于 UTF-8。

“UTF-8”是世界其他地方的名称。

常见错误:

  • 未能声明客户端的编码。
  • 尝试在客户端转换编码。
,

Visual Studio 允许您更改文件编码。 因此,如果您在变量上键入字符,则应该具有该编码。

在 Visual Studio 中或以编程方式设置选项 打开项目属性页对话框。 ... 选择配置属性 > C/C++ > 命令行属性页。 在附加选项中,添加 /utf-8 选项以指定您的首选编码。 选择确定以保存您的更改。 关联 https://docs.microsoft.com/en-us/cpp/build/reference/utf-8-set-source-and-executable-character-sets-to-utf-8?view=msvc-160

现在对于数据库,请确保您的数据库具有正确的字符集。 https://www.a2hosting.com/kb/developer-corner/mysql/convert-mysql-database-utf-8#:~:text=mysql-,q%20at%20the%20mysql%3E%20prompt

一旦您为 DB 和 Visual Studio 设置了正确的编码,您就可以保存编辑并从 C++ 代码中读取这些字符。