繁体   English   中英

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

[英]How to use UTF8 characters in DEFAULT c++ project OR when using mysql connector for c++ in visual studio 2019 (Latin7_general_ci to UTF-8)?

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

更新,更新 --- 我取得了小进展,如本文所述 - Visual Studio 2019 C++ 项目中的特殊字符并使用它们执行 CMD 命令

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

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

    cout << output << endl;
}

Intro rant* - This is 3rd post about MySql Connector, because I just could not find basic information about MySql Connector in Google at all ( MySQL and MariaDB library's in C++ using cmake, mingw ), first there was no explanation that GCC will not be able to compile it for Windows systems, then I had no luck finding how to use datetime and int objects in the output from database, until I posted issue here ( How to return time, date data fields in c++ mysql oracle vs17? ).

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

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

#include <iostream>
#include <string>
#include <string_view>

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

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

似乎对此没有太多了解,所以感谢您的帮助!

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

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

相反,它应该是

copy /-y C:\Users\Janis\Desktop\TEST2\Jānis.txt C:\PACIENTI\Jānis.txt
copy /-y C:\Users\Janis\Desktop\TEST2\Annā.txt C:\PACIENTI\Annā.txt

在此处输入图像描述

我认为您的问题与std::wstring无关:对于 UTF-8 来说,8 位std::string应该足够了(使用特殊字符"āàčīēļš"创建一个简单的std::string就可以了),而取决于操作系统, std::wstring是 2 字节 (Windows) 或 4 字节 (Linux)(更多信息在这里这里)。 毕竟,如果您查看getString function 您会看到它需要并返回一个sql::SQLString sql::SQLString class 只是std::string的简单包装器。

我认为您必须将utf-8 指定为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() << ").";
}

然后您应该可以继续查询您的数据库,如下所示

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

当您想使用它或 output 创建文件名到控制台时,现在出现的问题是Windows本身(我之前曾使用 Linux 测试过代码,因此之前没有遇到此问题:) 默认情况下,它使用 ANSI 而不是 UTF-8。 即使您使用 output 之类的āàčīēļš它也不会 output 正确,无论您是使用std::cout还是std::wcoutstd::wstring结合使用。 相反,它将 output ─ü├á─ì─½─ô─╝┼í

如果您提取字节

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

它将 output C4 81 C3 A0 C4 8D C4 AB C4 93 C4 BC C5 A1将其插入字节到 utf8 转换器,例如这个实际上会给你āàčīēļš 所以字符串被正确读取,但 Windows 只是没有正确显示它。 以下结合上一节(将utf-8指定为 MySql 中的默认字符集)应该可以解决您的所有问题:

  • 调用SetConsoleOutputCP(CP_UTF8); windows.h程序开始处的 windows.h 将修复控制台 output

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

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

为此,您需要将字符串转换为 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 - 表示存储在 exactable 中的字符串文字应编码为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内容复制到其他程序时,一切都正确显示(以防在我的程序中正确设置编码)。

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

玩一点这个程序我很确定这应该足以给你一个完整的画面。

最重要的:

  • std::locale::global定义了主程序使用的编码类型。 这意味着流假定std::string值以这种方式编码
  • std::iostream::imbue允许定义 stream 的编码,播种将写入文件的内容。
  • 这两个设置都定义了转换的双方! 您不必手动进行转换!

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

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

大概,你想要 utf8(或 utf8mb4)。

连接参数指定客户端的编码。 如果该十六进制字符串来自客户端,则指定 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 字节编码。 离开,但仍然适用于所有欧洲语言,以及世界上的大部分 rest。

“utf8mb4”是 MySQL 的 4 字节编码。 等效于 UTF-8。

“UTF-8”是它的世界名称rest。

常见错误:

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

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

在 Visual Studio 中设置选项或以编程方式打开项目属性页对话框。 ... Select 配置属性 > C/C++ > 命令行属性页。 在 Additional Options 中,添加 /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-,To%20change%20the%20character%20set%20encoding%20to% 20UTF%2D8%20for,q%20at%20the%20mysql%3E%20prompt

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM