Windows下提供了两个编码转换函数:WideCharToMultiByte 和 MultiByteToWideChar。用它们可实现Unicode(UCS2),UTF8,GBK(GB2312)互转。这两个函数的原型是:
int
WINAPI
MultiByteToWideChar(
__in UINT CodePage,
__in DWORD dwFlags,
__in_bcount(cbMultiByte) LPCSTR lpMultiByteStr,
__in int cbMultiByte,
__out_ecount_opt(cchWideChar) __transfer(lpMultiByteStr) LPWSTR lpWideCharStr,
__in int cchWideChar);
int
WINAPI
WideCharToMultiByte(
__in UINT CodePage,
__in DWORD dwFlags,
__in_ecount(cchWideChar) LPCWSTR lpWideCharStr,
__in int cchWideChar,
__out_bcount_opt(cbMultiByte) __transfer(lpWideCharStr) LPSTR lpMultiByteStr,
__in int cbMultiByte,
__in_opt LPCSTR lpDefaultChar,
__out_opt LPBOOL lpUsedDefaultChar);
第一个参数,CodePage,通常取两个值:
1、CP_UTF8,将Unicode与UTF8相互转换的时使用。
2、CP_ACP,Ansi Code Page,也就是计算机本地的代码页,中国大陆为936(简体中文),也就是GetACP()的返回值。Unicode与GBK相互转换时使用。
第二个参数,dwFlags,通常置0。
第三个参数,lpMultiByteStr或lpWideCharStr,是传入字符串的地址。
第四个参数,cbMultiByte或cchWideChar,是第三个参数的长度(cb是Count of Byte,即字节数;cch是Count of Char,即字符数)。若此值为1,字符串将被认为是以NULL结束的字符串,并且自动计算长度。
第五个参数,lpWideCharStr或lpMultiByteStr,是传出字符串的地址。
第六个参数,cchWideChar或cbMultiByte,是第五个参数的长度(cb是Count of Byte,即字节数;cch是Count of Char,即字符数)。若此值为0,函数返回目标缓冲区所必需的字符数。
后两个参数,lpDefaultChar和lpUsedDefaultChar,通常置0。只有当WideCharToMultiByte函数遇到一个宽字节字符,而该字符在uCodePage参数标识的代码页中并没有它的表示法时,WideCharToMultiByte函数才使用这两个参数。如果宽字节字符不能被转换,该函数便使用lpDefaultChar参数指向的字符。如果该参数是NULL(这是大多数情况下的参数值),那么该函数使用系统的默认字符。该默认字符通常是个问号。这对于文件名来说是危险的,因为问号是个通配符。pfUsedDefaultChar参数指向一个布尔变量,如果Unicode字符串中至少有一个字符不能转换成等价多字节字符,那么函数就将该变量置为TRUE。如果所有字符均被成功地转换,那么该函数就将该变量置为FALSE。当函数返回以便检查宽字节字符串是否被成功地转换后,可以测试该变量。
返回值,如果第五个参数为0,函数返回目标缓冲区所必须的字符数;否则,函数转换成功转换的字符数,函数失败时,返回0。
接下来,分享一个本人经常使用的,多字节与宽字节字符串转换的函数:
namespace
{
std::string wstring_to_string(const std::wstring& wstr, UINT cp = GetACP())
{
if (wstr.empty())
return std::string();
const wchar_t* u_str = wstr.c_str();
int u_len = (int)wstr.size();
int a_len = WideCharToMultiByte(cp, 0, u_str, u_len, NULL, 0, NULL, NULL);
if (a_len == 0)
return std::string();
std::vector astr(a_len);
char* a_str = &astr.front();
WideCharToMultiByte(cp, 0, u_str, u_len, a_str, a_len, NULL, NULL);
return std::string(astr.begin(), astr.end());
}
std::wstring string_to_wstring(const std::string& astr, UINT cp = GetACP())
{
if (astr.empty())
return std::wstring();
const char* a_str = astr.c_str();
int a_len = (int)astr.size();
int u_len = MultiByteToWideChar(cp, 0, a_str, a_len, NULL, 0);
if (u_len == 0)
return std::wstring();
std::vector wstr(u_len);
wchar_t* u_str = &wstr.front();
MultiByteToWideChar(cp, 0, a_str, a_len, u_str, u_len);
return std::wstring(wstr.begin(), wstr.end());
}
}