这几天帮一个朋友修改一个产品,这个产品是在Windows下通过C++的mysql++去访问mysql数据库,同时,该产品的数据需要支持多语言(中文、日文、韩文、法文等)。而mysql对于多语言的支持采用的字符集是utf8,但是,在windows下的vs中是采用unicode,这样就需要进行字符集的转化。而该产品的代码中,又使用了STL的string,这样就更麻烦了。
因此,在往mysql++传入sql语句的之前,需要先把string(ANSI)转为宽字节(wchar_t),然后再从宽字节转为UTF8格式。
所以,第一步ANSI转为宽字节(wchar_t)
int CharSetUtility::Chr2Wchr(const char* pIn,wchar_t*& pOut){ size_t len = strlen(pIn); size_t wlen = MultiByteToWideChar(CP_ACP, 0, (const char*)pIn, int(len), NULL, 0); pOut = new wchar_t[wlen + 1]; int ret = MultiByteToWideChar(CP_ACP, 0, (const char*)pIn, int(len), pOut, int(wlen)); *(pOut + wlen) = L'/0'; return ret; }
其中,MultiByteToWideChar这个函数是Windows的API,是在文件atlconv.h中声明的。具体该函数的相关说明在msdn有详细的说明了。这里面就不多说了。
第二步宽字节转为UTF8
int CharSetUtility::W2UTF8(const wchar_t* pIn, char*& pOut){ DWORD dwNum = WideCharToMultiByte(CP_UTF8,NULL,pIn,-1,NULL,0,NULL,FALSE); pOut = new char[dwNum + 1]; int ret = WideCharToMultiByte (CP_UTF8,NULL,pIn,-1,pOut,dwNum,NULL,FALSE); *(pOut + dwNum) = '/0'; delete pW; return ret; }
同样,WideCharToMultiByte也是Windows的API。
在从mysql中取出数据格式也是UTF8,要显示这些数据,也需要对这些数据进行字符集的转换,需要转为ANSI或者UNICODE。
int CharSetUtility::UTF82C(const char* pIn,std::string& strOut){ DWORD dwNum = MultiByteToWideChar(CP_UTF8,NULL ,pIn,-1, NULL, 0); wchar_t* pwOut = new wchar_t[dwNum + 1]; memset(pwOut, 0, dwNum * sizeof(wchar_t)); int ret = MultiByteToWideChar(CP_UTF8,NULL ,pIn,-1, pwOut, dwNum); dwNum = WideCharToMultiByte(CP_OEMCP,NULL,pwOut,-1,NULL,0,NULL,FALSE); char *psText = new char[dwNum + 1]; WideCharToMultiByte (CP_OEMCP,NULL,pwOut,-1,psText,dwNum,NULL,FALSE); *(psText + dwNum) = '/0'; strOut = psText; delete []psText; return ret; }
另外,在mysql++中,为了与mysql数据传输采用UTF8格式的话,需要在创建连接之前,设置字符集为UTF8;
具体是调用mysqlpp::Connection的set_option函数,参数是new SetCharsetNameOption("utf8");
比如:mysqlCon.set_option(new SetCharsetNameOption("utf8"),不过,一定要是在connect函数调用之前调用。