acl中C++連接MySQL數據庫插入和獲取記錄中文字符亂碼問題

字符編碼真是個頭痛的問題,以前一直不放在心上,現在用到了才發現真的麻煩。

花了將近一天的時間終於達到目的。

測試環境VS2017+MYSQL8,各種編碼的具體說明就不講了,自行百度。

1、讀取數據亂碼問題:

vs項目下,默認編碼Unicode,但我的數據庫默認utf8,所以讀取數據的時候中文亂碼。

百度了一下,發現只要將utf8字符轉成unicode字符即可,轉換函數如下:


wchar_t* Utf8_2_Unicode(char* row_i)
{
    int len = MultiByteToWideChar(CP_UTF8, 0, row_i, strlen(row_i), NULL, 0);
    wchar_t *wszStr = new wchar_t[len + 1];
    MultiByteToWideChar(CP_UTF8, 0, row_i, strlen(row_i), wszStr, len);
    wszStr[len] = '\0';
    return wszStr;
}
在函數外部定義一個wchar_t*類型變量接收返回值即可正確輸出。

2、寫入數據亂碼

解決了讀取出錯後以爲讀取只要反向轉換就行,但是把接收到的utf8字符轉換成unicode後並不能行。

然後在網上各種百度,然後又各種類型轉換編碼轉換人都弄暈了,總是圍繞utf8轉來轉去,沒有一點成效。

最後看了一個帖子,說要以gbk形式寫入,在內心抱着極度懷疑的情況下試了一下,沒想到竟然成功了。

其實這個帖子看了很多遍了,在心裏默默的排除了一萬遍沒想到最後竟然它纔是有用的。

方法很簡單,只要在寫入之前設置編碼爲gbk即可。
strcpy_s(sql, "set names gbk");

3、完整的測試代碼


#include "d:/include/mysql.h"
#include <iostream>
#include <windows.h>
#include <tchar.h>
using namespace std;
 
#pragma  comment(lib, "d:/lib/libmysql.lib")
 
wchar_t* Utf8_2_Unicode(char* row_i)
{
    int len = MultiByteToWideChar(CP_UTF8, 0, row_i, strlen(row_i), NULL, 0);
    wchar_t *wszStr = new wchar_t[len + 1];
    MultiByteToWideChar(CP_UTF8, 0, row_i, strlen(row_i), wszStr, len);
    wszStr[len] = '\0';
    return wszStr;
}
void showError(const char * error)
{
    cout << error << endl;
    getchar();
}
int main()
{
    MYSQL mysql;
    MYSQL *connect;
    //初始化MYSQL
    connect =  mysql_init(&mysql);
    if (connect == NULL)
    {
        showError(mysql_error(connect));
        return mysql_errno(connect);
    }
    cout << "Init OK" << endl;
    //連接到MYSQL
    connect = mysql_real_connect(connect, "localhost", "root", "123456", "mytest", 3306, NULL, 0);
    if (connect == NULL)
    {
        showError(mysql_error(connect));
        return mysql_errno(connect);
    }
    cout << "Connect OK" << endl;
    char sql[256] = {0};
    //將編碼設置爲gbk
    strcpy_s(sql, "set names gbk");
    if (mysql_query(connect, sql))
    {
        showError(mysql_error(connect));
        return mysql_errno(connect);
    }

    //寫入中文數據
    strcpy_s(sql, "INSERT INTO test(m1, m2) VALUES('測試', 'Test')");
    if (mysql_query(connect, sql))
    {
        showError(mysql_error(connect));
        return mysql_errno(connect);
    }
    cout << "Insert success!\n";
    //設置編碼格式utf8
    strcpy_s(sql, "set names utf8");
    int ret = mysql_query(connect, sql);
    if (ret)
    {
        showError(mysql_error(connect));
        return mysql_errno(connect);
    }
    //讀取中文數據
    strcpy_s(sql, "SELECT * FROM test");
    ret = mysql_query(connect, sql);
    if (ret)
    {
        showError(mysql_error(connect));
        return mysql_errno(connect);
    }
    else
    {
        //獲取結果集
        MYSQL_RES *res = mysql_store_result(connect);
        if (mysql_num_rows(res) == NULL)
        {
            showError(mysql_error(connect));
            return mysql_errno(connect);
        }
        int nfieldNum = mysql_num_fields(res);
        MYSQL_ROW row;
        //取出結果集
        while (row = mysql_fetch_row(res))
        {
            wchar_t *m1, *m2;
            //將字符由utf8專轉爲unicode
            m1 = Utf8_2_Unicode(row[0]);
            m2 = Utf8_2_Unicode(row[1]);
            MessageBox(NULL, m1, m2, NULL);
        }
        mysql_free_result(res);
    }
    mysql_close(connect);
    getchar();
    return 0;
}

 

在acl中直接下面這樣即可(寫的時候gbk,讀的時候utf8mb4):

    // 連接池中最大連接數量限制
    int  dblimit = 10;
    // 創建數據庫連接池對象
    acl::mysql_conf dbconf(dbip_.c_str(), dbname_.c_str());
    dbconf.set_dbuser(dbuser_.c_str()).set_dbpass(dbpwd_.c_str()).set_dblimit(dblimit);
    dbconf.set_charset("gbk");

 

在acl每個寫入語句前用set names測試,聯合workbench查詢中的幾個測試:

acl中用gbk寫入成功,讀取用utf8mb4無亂碼也成功;

acl中用utf8mb4寫入直接報錯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章