博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
“Unicode字符集”和“多字符集”(Multi-Byte)”的转换!~

函数分别为:
见MSDN的ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.WIN32COM.v10.en/intl/unicode_2bj9.htm
int WideCharToMultiByte(
UINT
CodePage,            // code page
DWORD dwFlags,            // performance and mapping flags
LPCWSTR lpWideCharStr,    // wide-character string
int cchWideChar,          // number of chars in string.
LPSTR lpMultiByteStr,     // buffer for new string
int cbMultiByte,          // size of buffer
LPCSTR lpDefaultChar,     // default for unmappable chars
LPBOOL lpUsedDefaultChar // set when default char used
);

见MSDN的ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.WIN32COM.v10.en/intl/unicode_17si.htm
int MultiByteToWideChar(
UINT CodePage,
DWORD dwFlags,
LPCSTR lpMultiByteStr,
int cbMultiByte,
LPWSTR lpWideCharStr,
int cchWideChar
);

============================================================================

以下内容转自:http://www.crazycoder.cn/CDevelopment/Article14240.html

我不知道VC.net2005默认工程默认设置是采用“Unicode字符集”(Unicode Character Set)的,以前用VC6工程的时候默认是“多字符集”(Multi-Byte Character Set)的。以前也没有用过VC.net2005啊,我一直认为.net是用来在framework上面编程的,在MFC上编程没有必要打开庞大的.net2005,把机器弄得像牛拉车一样。

我声明了一个CString,按计划给它赋值,就像下面:

CString s;
s.Format(“count = %d”,count);

按经验这肯定不会有错误的,但是不好意思,编译错误,因为这是我的环境采用的Unicode字符集的,而我给CString的Format函数是“多字符集”(Multi-Byte)所以编译不通过,要知道在这种设置下使用MessageBox(“ddd”);编译是不会通过的,因为系统调用的是MessageBoxW,即Unicode宽字符集的那个函数。

还好我根据编译器的提示把s.Format(“count = %d”,count);改成s.Format(_T(“count = %d”,count);就搞定了,_T代表一个宏,宏的意思就是把字符串转成宽字符表示。同样的,MessageBox(“ddd”);可以为MessageBox(_T(“ddd”));

但是还有个问题就是,所有窗体显示的东西都是宽字符的,例如a在内存里就是a\0两个字节,前面一个字节a后面是\0,当从窗体取下数据(例如用户输入)要跟其他平台交互时,例如网络传输到远端机器。如果那边使用的不是Unicode字符集,就会出问题,为了使界面和后台传输一致,只好使用把宽字符转换成多字符集表示:

CString strWideChar;
strWideChar.Format(_T("这是宽字节哦"));
char buf[20];
memset(buf,0,20);

WideCharToMultiByte( //转换Unicode到Ansi
CP_ACP,
WC_COMPOSITECHECK | WC_DEFAULTCHAR,
strWideChar,
strWideChar.GetLength(),
(char *)buf, //转换到缓冲区中
20, //最多个字节
0,
0
);

同样的,你接收到的字符串想要在界面正常显示,还必须把它转换成宽字节表示(烦吧?):

 

char chBytes[8];

memcpy(chBytes,"aaaaaaa\0",8);
WCHAR wch[9];

n = MultiByteToWideChar( //转换Unicode到Ansi
CP_ACP,
0,
chBytes,
8,
wch, //转换到缓冲区中
8 //最多个字节
);

wch[n] = '\0';

这样每次从界面取数据和把数据显示到界面上都要先做处理,但是也可以把编译环境设置成“多字符集”(Multi-Byte Character Set),就可以避免这样转换来转换去(可惜我发现的时候代码已经差不多写完了)。就是在”Project->Configuration Properties->General->Character Set,选择“Use Unicode Character Set”就是使用Uncode字符集,选择” Use Multi-Byte Character Set”就是多字节字符集。

=============================================================================================================

最近在进行一项工作,用VC6编写一个连接mysql进行存取数据的程序。

本来打算使用便利的ADO进行操作,但研究了一下,发现ADO不能直接连接mysql,必须通过ODBC。而ODBC虽然编写程序的时候方便,但使用起来较麻烦,而且据说稳定性和效率都不太好。所以最终决定用mysql提供的API。

mysql提供的API优点很明显,效率高,稳定。缺点有,它本身是for C,不是for C++,所以相比其它MFC程序的编写显示得不那么便利。它的通用性差,代码的可移植性几乎为0。但最大的问题则在于它的编码问题。

首先这个程序必须在简体和繁体系统都能正常显示文字,这样程序必须使用unicode字符。再来,数据库方面,要正确保存从简体和繁体系统中存入的数据,而且无论从简体还是繁体系统甚至日文系统中读取这些数据时都能正确显示,且不是乱码。而mysql不支持unicode编码,它的API甚至不能执行unicode编码的sql语句。mysql支持的utf8编码,又不能在VC6编写的程序上正常显示……

经过研究之后,决定这样解决问题。程序采用unicode编码,数据库用utf8编码。程序中执行sql语句之前,将Unicode编码的sql转为utf8编码执行。从数据库中取出的utf8数据转为unicode在程序上显示。其中两个关键的函数如下:


//将UTF8编码的字串转为Unicode返回为CString
//for unicode only
CString CTS04Dlg::UTF8ToUnicode(char* UTF8)
{
    DWORD dwUnicodeLen;        //转换后Unicode的长度
    TCHAR *pwText;            //保存Unicode的指针
    CString strUnicode;        //返回值

    //获得转换后的长度,并分配内存
    dwUnicodeLen = MultiByteToWideChar(CP_UTF8,0,UTF8,-1,NULL,0);
    pwText = new TCHAR[dwUnicodeLen];
    if (!pwText)
    {
        return strUnicode;
    }

    //转为Unicode
    MultiByteToWideChar(CP_UTF8,0,UTF8,-1,pwText,dwUnicodeLen);

    //转为CString
    strUnicode.Format(_T("%s"),pwText);

    //清除内存
    delete []pwText;

    //返回转换好的Unicode字串
    return strUnicode;
}

//通过mysql的API执行Unicode编码的sql语句
//数据表的编码为utf8
BOOL CTS04Dlg::ExecuteUnicodeSQL(CString strSQL)
{
    DWORD dwUTF8Len;    //保存UTF8编码sql的长度
    char* psText;        //保存UTF8编码sql的指针

    //获得UTF8编码sql的长度,并分配内存
    dwUTF8Len = WideCharToMultiByte(CP_UTF8,NULL,(LPCTSTR)strSQL,-1,NULL,0,NULL,FALSE);
    psText = new char[dwUTF8Len];
    if (!psText)
    {
        return FALSE;
    }

    //将Unicode编码的sql转为utf8编码
    WideCharToMultiByte(CP_UTF8,NULL,(LPCTSTR)strSQL,-1,psText,dwUTF8Len,NULL,FALSE);

    //调用mysql的API执行sql语句
    if(mysql_real_query(&mysql,psText,dwUTF8Len) != 0)
    {
        delete []psText;
        return FALSE;
    }

    //清除内存
    delete []psText;

    //返回执行成功
    return TRUE;
}