C++ sqlite3解决中文排序问题

导言:sqlite3默认的编码方式为UTF8编码,而在UTF8编码下,中文不是按照拼音顺序编码的,所以想解决中文排序问题,必须自定义排序规则,将UTF8编码转换成GB2312编码(GB2312编码中文是按照拼音顺序编码的),然后再进行比较大小,就可以得到正确的排序结果了。

#include "sqlite3.h"
#include <Windows.h>

#include <string>
#include <vector>
using std::vector;
using std::string;
#pragma comment(lib, "sqlite3.lib")
//UTF-8到GB2312的转换
void U2G(const char* utf8, string& gb2312)
{
    int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
    wchar_t* wstr = new wchar_t[len+1];
    memset(wstr, 0, len+1);
    MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, len);
    len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
    char* str = new char[len+1];
    memset(str, 0, len+1);
    WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);
    if(wstr) delete[] wstr;
    gb2312 = str;
    delete[] str;
}
 
//GB2312到UTF-8的转换
void G2U(const char* gb2312, string& utf8)
{
    int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);
    wchar_t* wstr = new wchar_t[len+1];
    memset(wstr, 0, len+1);
    MultiByteToWideChar(CP_ACP, 0, gb2312, -1, wstr, len);
    len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
    char* str = new char[len+1];
    memset(str, 0, len+1);
    WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
    if(wstr) delete[] wstr;
    utf8 = str;
    delete[] str;
}

int chinese_cmp(void *NotUsed, int nKey1, const void *pKey1, int nKey2, const void *pKey2)
{
    //int n = nKey1 < nKey1 ? nKey1 : nKey2;
    string key1 = "";
    string key2 = "";
    U2G((char*)pKey1,key1);
    U2G((char*)pKey2,key2);
    //return strncmp(key1.c_str(), key2.c_str(), n + 1);
    return strcmp(key1.c_str(), key2.c_str());
}

void main()
{
    sqlite3* conn;
    int ret = sqlite3_open("C:\\Users\\Administrator\\Desktop\\testsort.db", &conn);
    sqlite3_create_collation(conn, "Chinese", SQLITE_UTF8, 0, chinese_cmp);

    string sql = "";
    G2U("select * from mzhrd order by xm collate Chinese", sql);
    sqlite3_stmt *stmt;
    ret = sqlite3_prepare_v2(conn, sql.c_str(), sql.length(), &stmt,0);

    while(sqlite3_step(stmt) != SQLITE_DONE)
    {
        string data = "";
        U2G((char*)sqlite3_column_text(stmt,0),data);
        int afsd =1;
    }
    int dsaf = 1;
}