WideCharToMultiByte和MultiByteToWideChar函数的用法

本文介绍了如何在Windows环境下使用WideCharToMultiByte和MultiByteToWideChar函数进行Unicode与多字节之间的转换,并提供了ANSI与Unicode、UTF-8与Unicode相互转换的具体代码实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为了支持Unicode编码,需要多字节与宽字节之间的相互转换。这两个系统函数在使用时需要指定代码页,在实际应用过程中遇到乱码问题,然后重新阅读《Windows核心编程》,总结出正确的用法。
WideCharToMultiByte的代码页参数用来标记目的字符串相关的代码页。
MultiByteToWideChar的代码页参数用来标记源多字节字符串相关的代码页。

常用的代码页由CP_ACP(或CP_OEMCP)和CP_UTF8两个。
使用CP_ACP代码页就实现了ANSI与Unicode之间的转换。
使用CP_UTF8代码页就实现了UTF-8与Unicode之间的转换。

下面是代码实现:
1.  ANSI to Unicode
wstring ANSIToUnicode( const string& str )
{
 int  len = 0;
 len = str.length();
 int  unicodeLen = ::MultiByteToWideChar( CP_ACP,
            0,
            str.c_str(),
            -1,
            NULL,
            0 ); 
 wchar_t *  pUnicode; 
 pUnicode = new  wchar_t[unicodeLen+1]; 
 memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t)); 
 ::MultiByteToWideChar( CP_ACP,
         0,
         str.c_str(),
         -1,
         (LPWSTR)pUnicode,
         unicodeLen ); 
 wstring  rt; 
 rt = ( wchar_t* )pUnicode;
 delete  pUnicode;
 
 return  rt; 
}
2.  Unicode to ANSI
string UnicodeToANSI( const wstring& str )
{
 char*     pElementText;
 int    iTextLen;
 // wide char to multi char
 iTextLen = WideCharToMultiByte( CP_ACP,
         0,
         str.c_str(),
         -1,
         NULL,
         0,
NULL,
         NULL );
 pElementText = new char[iTextLen + 1];
 memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
 ::WideCharToMultiByte( CP_ACP,
         0,
         str.c_str(),
         -1,
         pElementText,
         iTextLen,
         NULL,
         NULL );
 string strText;
 strText = pElementText;
 delete[] pElementText;
 return strText;
}
3.  UTF-8 to Unicode
wstring UTF8ToUnicode( const string& str )
{
 int  len = 0;
 len = str.length();
 int  unicodeLen = ::MultiByteToWideChar( CP_UTF8,
            0,
            str.c_str(),
            -1,
            NULL,
            0 ); 
 wchar_t *  pUnicode; 
 pUnicode = new  wchar_t[unicodeLen+1]; 
 memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t)); 
 ::MultiByteToWideChar( CP_UTF8,
         0,
         str.c_str(),
         -1,
         (LPWSTR)pUnicode,
         unicodeLen ); 
 wstring  rt; 
 rt = ( wchar_t* )pUnicode;
 delete  pUnicode;
 
 return  rt; 
}
4.  Unicode to UTF-8   
string UnicodeToUTF8( const wstring& str )
{
 char*     pElementText;
 int    iTextLen;
 // wide char to multi char
 iTextLen = WideCharToMultiByte( CP_UTF8,
         0,
         str.c_str(),
         -1,
         NULL,
         0,
         NULL,
         NULL );
 pElementText = new char[iTextLen + 1];
 memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
 ::WideCharToMultiByte( CP_UTF8,
         0,
         str.c_str(),
         -1,
         pElementText,
         iTextLen,
         NULL,
         NULL );
 string strText;
 strText = pElementText;
 delete[] pElementText;
 return strText;

}

 

附:CP_ACP和CP_OEMCP的关系

CP_ACP和CP_OEMCP,分别是指当前计算机操作系统的Windows代码页与OEM代码页。对于东亚的简体中文、繁体中文、日文、韩文等Win操作系统语言环境,这两种代码页是同一个,如简体中文是代码页936即GB2312字符集,繁体中文是950即大五码字符集,韩文是949、日文是932。对于西方国家的拼音文字语言设置,两个代码页不同。典型的如English_US,其Windows代码页是1252、OEM代码页是437,还有第三个代码页ISO-8859-1又称Latin-1或“西欧语言”,是针对英语法语西语德语等西欧语言的扩展ASCII字符集。这三者(1252、437、8859-1)都是针对英语但并不相同。

为什么会有Windows代码页与OEM代码页的区别呢?因为在八十年代DOS系统时期,还是“字符终端”的屏幕只能够显示的256个字符,这些字符的字形的点阵信息存储在硬件的ROM中。DOS操作系统通过系统中断调用驱动程序把这些字形读出来写入显存。这是由OEM负责字符集中有哪些字符,显示时为什么字形的时代,而且一台PC上只有这么一套字符集/字形,没得选,除非你再差一个带字库的“汉卡”。进入了微软的Windows操作系统时代之后,由于硬件的发展,操作系统有了自己的字形文件,绘制字符时不再真地去读ROM,而是用字形文件(就是字体fonts文件)来把字符的形状写入显存。可以选择用哪种字形:如有衬线的Times NewRome,还是无衬线的Sans Serif。操作系统默认使用的字符集,就由微软来定义了,如English_US使用Codepage1252;简体中文使用Codepage936(即国标2312). 至于那个OEM436,就是legacy,用于向后兼容。

综上,就这么点事。CP_ACP和CP_OEMCP,分别是UINT的0和1。在WinNls.h中的注释说明分别是“default to ANSI code page”,“default to OEM  code page”。所以,在简体中文Windows,这两个宏表示的都是代码页936.

MultiByteToWideCharWideCharToMultiByteWindows API中用于UnicodeANSI字符串之间的转换的函数。下面是它们的使用方法参数详解: ### MultiByteToWideChar ```c++ int MultiByteToWideChar( UINT CodePage, //转换的代码页,如CP_UTF8 DWORD dwFlags, //转换标志,如MB_ERR_INVALID_CHARS LPCSTR lpMultiByteStr, //输入的ANSI字符串 int cbMultiByte, //输入的ANSI字符串的字节数 LPWSTR lpWideCharStr, //输出的Unicode字符串 int cchWideChar //输出的Unicode字符串的字符数 ); ``` - CodePage:转换的代码页,如CP_UTF8表示UTF-8编码。如果为0,则表示使用当前系统的ANSI代码页。 - dwFlags:转换标志,如MB_ERR_INVALID_CHARS表示如果输入的ANSI字符串中包含无法转换的字符,则返回一个错误。 - lpMultiByteStr:输入的ANSI字符串。 - cbMultiByte:输入的ANSI字符串的字节数。如果为-1,则表示输入的字符串是以NULL结尾的字符串。 - lpWideCharStr:输出的Unicode字符串。 - cchWideChar:输出的Unicode字符串的字符数。如果为0,则表示函数返回需要的缓冲区大小(以字符为单位)。 ### WideCharToMultiByte ```c++ int WideCharToMultiByte( UINT CodePage, //转换的代码页,如CP_UTF8 DWORD dwFlags, //转换标志,如WC_ERR_INVALID_CHARS LPCWSTR lpWideCharStr, //输入的Unicode字符串 int cchWideChar, //输入的Unicode字符串的字符数 LPSTR lpMultiByteStr, //输出的ANSI字符串 int cbMultiByte, //输出的ANSI字符串的字节数 LPCSTR lpDefaultChar, //无法转换的Unicode字符的默认ANSI字符 LPBOOL lpUsedDefaultChar //是否使用了默认字符 ); ``` - CodePage:转换的代码页,如CP_UTF8表示UTF-8编码。如果为0,则表示使用当前系统的ANSI代码页。 - dwFlags:转换标志,如WC_ERR_INVALID_CHARS表示如果输入的Unicode字符串中包含无法转换的字符,则返回一个错误。 - lpWideCharStr:输入的Unicode字符串。 - cchWideChar:输入的Unicode字符串的字符数。如果为-1,则表示输入的字符串是以NULL结尾的字符串。 - lpMultiByteStr:输出的ANSI字符串。 - cbMultiByte:输出的ANSI字符串的字节数。如果为0,则表示函数返回需要的缓冲区大小(以字节为单位)。 - lpDefaultChar:无法转换的Unicode字符的默认ANSI字符。 - lpUsedDefaultChar:输出参数,指示是否使用了默认字符。 注意事项: - 如果输入的ANSI字符串中包含无法转换的字符,则需要设置dwFlags为MB_ERR_INVALID_CHARS,否则函数会返回一个错误。 - 如果输入的Unicode字符串中包含无法转换的字符,则需要设置dwFlags为WC_ERR_INVALID_CHARS,否则函数会返回一个错误。 - 在使用WideCharToMultiByte函数时,如果输出的ANSI字符串中包含多字节字符,则需要使用一个足够大的缓冲区,否则函数会返回一个错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值