Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1222603
  • 博文数量: 233
  • 博客积分: 6270
  • 博客等级: 准将
  • 技术积分: 1798
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-26 08:32
文章分类

全部博文(233)

文章存档

2011年(31)

2010年(202)

我的朋友

分类: WINDOWS

2010-08-25 09:15:36

【Juexun注:在实现linux和wince平台之间的数据通信的时候,遇到了一个小问题,linux发送(发送前进行utf8到gb2312的转换)到CE的中文总是无法显示出来,而CE发送到Linux的中文能正常显示(linux端有进行gb2312到utf8的转换),在网上收集了一下资料,汇总如下】
 

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

 

以下为更详细的说明,不烦请详细阅读:

原文地址为:

http://hi.baidu.com/kalcaddle/blog/item/3709c5097cd37b3ce8248844.html

MultiByteToWideChar和
WideCharToMultiByte用法详解

函数原型:

int WideCharToMultiByte(

UINT CodePage,

DWORD dwFlags,

LPCWSTR lpWideCharStr,

int cchWideChar,

LPSTR lpMultiByteStr,

int cbMultiByte,

LPCSTR lpDefaultChar,

LPBOOL lpUsedDefaultChar

);

此函数把宽字符串转换成指定的新的字符串,如ANSIUTF8等,新字符串不必是多字节字符集。参数:

CodePage 指定要转换成的字符集代码页,它可以是任何已经安装的或系统自带的字符集,你也可以使用如下所示代码页之一。

参数说明:
1、CodePage——指定要转换成的字符集代码页,它可以是任何已经安装的或系统自带的字符集,可选择以下代码页:
CP_ACP   //当前系统ANSI代码页
          CP_MACCP   //当前系统Macintosh代码页
          CP_OEMCP   //当前系统OEM代码页,一种原始设备制造商硬件扫描码
          CP_SYMBOL //Symbol代码页,用于Windows 2000及以后版本
          CP_THREAD_ACP //当前线程ANSI代码页,用于Windows 2000及以后版本
          CP_UTF7 //UTF-7,设置此值时lpDefaultChar和lpUsedDefaultChar都必须为NULL
          CP_UTF8 //UTF-8,设置此值时lpDefaultChar和lpUsedDefaultChar都必须为NULL
          用 GetLocaleInfo 函数获取当前系统的代码页,936: 简体中文, 950: 繁体中文,949:韩文
2、dwFlags—— 一般用 0 就可以了
          指定是否转换成预制字符或合成的宽字符,对控制字符是否使用像形文字,以及怎样处理无效字符:
          MB_PRECOMPOSED //总是使用预制字符,即有单个预制字符时,就不会使用分解的基字符和不占空间字符。此为函数的默认选项,不能和MB_COMPOSITE合用MB_COMPOSITE //总是使用分解字符,即总是使用基字符+不占空间字符的方式
MB_ERR_INVALID_CHARS //设置此选项,函数遇到非法字符就失败并返回错误码

ERROR_NO_UNICODE_TRANSLATION,否则丢弃非法字符
MB_USEGLYPHCHARS //使用像形字符代替控制字符
3、lpMultiByteStr //要转换的字符串
4、cbMultiByte //要转换字符串的长度,-1表示转换到字符串结尾。返回原字符串长度。0 作为结束符的字符串
5、lpWideCharStr//接收转换后输出的宽字符串的缓冲,如果为 NULL, 就是代表计算生成的字符串的长度。
6、cchWideChar//输出缓冲区大小,转化生成的 unicode 字符串缓存的容量。如果为0,lpMultiByteStr将被忽略,函数将返回所需缓冲区大小而不同
     为0表示调用失败;当cchWideChar为0时,函数将返回所需缓冲区大小
int BufSize = MultiByteToWideChar(936,0,s,-1,NULL,0); //计算简体中文字符串 s 转成 widestring 之后占用的内存字节数…… //在此处为 wsbuf 分配内存 BufSize 个字节
MultiByteToWideChar(936,0,s,-1,wsbuf,BufSize); //把简体中文字符串 s 转化为 unicode 的 WideString
最常用的应该是CP_ACP和CP_UTF8了,前者将宽字符转换为ANSI,后者转换为UTF8。

例一:Unicode转换到GBK
#include
#define CODE_PAGE_GB18030 54936
int Unicode2GBK( wchar_t *pUnicode, char** ppDest)
{ // get the size of the dest string
const int size = ::WideCharToMultiByte( CODE_PAGE_GB18030, 0/* you can do more for it*/,

pUnicode, -1, 0, 0, 0, 0 );
if ( size == 0 ) { return -1; }
char* pDestString = new char[size + 2];
::memset( pDestString, 0, sizeof(pDestString) );
// transform
int ret = ::WideCharToMultiByte( CODE_PAGE_GB18030, 0, pUnicode, -1, pDestString, size, 0, 0 );
if( ret == 0 ) { delete pDestString; return -1; }
else { *ppDest = pDestString; return 0; } }
例二:字串转换
wchar_t* pwszUnicode = "Holle, word! 你好,中国! ";
int iSize;
char* pszMultiByte;
iSize = WideCharToMultiByte(CP_ACP, 0, pwszUnicode, -1, NULL, 0, NULL, NULL);
pszMultiByte = (char*)malloc((iSize+1)/**sizeof(char)*/);
WideCharToMultiByte(CP_ACP, 0, pwszUnicode, -1, pszMultiByte, iSize, NULL, NULL);

注意事项:
dwFlags: 指定如何处理没有转换的字符, 但不设此参数函数会运行的更快一些,我都是把它设为0。 可设的值如下表所示:
WC_NO_BEST_FIT_CHARS 把不能直接转换成相应多字节字符的Unicode字符转换成lpDefaultChar指定的默认字符。也就是说,如果把Unicode转换成多字节字符,然后再转换回来,你并不一定得到相同的Unicode字符,因为这期间可能使用了默认字符。此选项可以单独使用,也可以和其他选项一起使用。
WC_COMPOSITECHECK 把合成字符转换成预制的字符。它可以与后三个选项中的任何一个组合使用,如果没有与他们中的任何一个组合,则与选项WC_SEPCHARS相同。
WC_ERR_INVALID_CHARS 此选项会致使函数遇到无效字符时失败返回,并且GetLastError会返回错误码ERROR_NO_UNICODE_TRANSLATION。否则函数会自动丢弃非法字符。此选项只能用于UTF8。

     WC_DISCARDNS 转换时丢弃不占空间的字符,与WC_COMPOSITECHECK一起使用
     WC_SEPCHARS 转换时产生单独的字符,此是默认转换选项,与WC_COMPOSITECHECK一起使用
     WC_DEFAULTCHAR 转换时使用默认字符代替例外的字符,(最常见的如’?’),与WC_COMPOSITECHECK一起使用。
     当指定WC_COMPOSITECHECK时,函数会将合成字符转换成预制字符。合成字符由一个基字符和一个不占空间的字符(如欧洲国家及汉语拼音的音标)组成,每一个都有不同的字符值。预制字符有一个用于表示基字符和不占空间字符的合成体的单一的字符值。
     当指定WC_COMPOSITECHECK选项时,也可以使用上表列出的最后3个选项来定制预制字符的转换规则。这些选项决定了函数在遇到宽字符串的合成字符没有对应的预制字符时的行为,他们与WC_COMPOSITECHECK一起使用,如果都没有指定,函数默认WC_SEPCHARS。
  
   对于下列代码页,dwFlags必须为0,否则函数返回错误码ERROR_INVALID_FLAGS。
50220 5022150222 50225 50227 50229 52936 54936 57002到5701165000(UTF7) 42(Symbol)

     对于UTF8,dwFlags必须为0或WC_ERR_INVALID_CHARS,否则函数都将失败返回并设置错误码ERROR_INVALID_FLAGS,你可以调用GetLastError获得。
lpUsedDefaultChar:开关变量的指针,用以表明是否使用过默认字符。对于要求此参数为NULL的dwFlags

     而使用此参数,函数将失败返回并设置错误码ERROR_INVALID_PARAMETER。lpDefaultChar和lpUsedDefaultChar都设为NULL,函数会更快一些。

第二个是多字节字符到宽字符转换函数,函数原型如下:
> int MultiByteToWideChar(
UINT CodePage,
DWORD dwFlags,
LPCSTR lpMultiByteStr,
int cbMultiByte,
LPWSTR lpWideCharStr,
int cchWideChar
);
此函数把多字节字符串转换成宽字符串(Unicode),待转换的字符串并不一定是多字节的。
此函数的参数,返回值及注意事项参见上面函数WideCharToMultiByte的说明,这里只对dwFlags做简单解释。
dwFlags: 指定是否转换成预制字符或合成的宽字符,对控制字符是否使用像形文字,以及怎样处理无效字符。
     MB_PRECOMPOSED 总是使用预制字符,即有单个预制字符时,就不会使用分解的基字符和不占空间字符。此为函数的默认选项,不能和MB_COMPOSITE合用
     MB_COMPOSITE 总是使用分解字符,即总是使用基字符+不占空间字符的方式
     MB_ERR_INVALID_CHARS 设置此选项,函数遇到非法字符就失败并返回错误码               ERROR_NO_UNICODE_TRANSLATION,否则丢弃非法字符
     MB_USEGLYPHCHARS 使用像形字符代替控制字符

     对于下列代码页,dwFlags必须为0,否则函数返回错误码ERROR_INVALID_FLAGS。
50220 5022150222 50225 50227 50229 52936 54936 57002到5701165000(UTF7) 42(Symbol)

对于UTF8,dwFlags必须为0或MB_ERR_INVALID_CHARS,否则函数都将失败并返回错误码ERROR_INVALID_FLAGS。
     以下函数我没用过,只简要说明之。
int GetTextCharset( HDC hdc );
此函数获取当前选进的设备描述表的字符集,等同于GetTextCharsetInfo(hdc, NULL, 0)。
返回值: 成功返回字符集标识,失败返回DEFAULT_CHARSET。

1.使用方法详解
在本文开始之处,先简要地说一下何为短字符和宽字符.
所谓的短字符,就是用8bit来表示的字符,典型的应用是ASCII码.而宽字符,顾名思义,就是用16bit表示的字符,典型的有UNICODE.关于windows下的ASCII和UNICODE的更多信息,可以参考这两本经典著作:《windows 程序设计》,《windows 核心编程》.这两本书关于这两种字符都有比较详细的解说.

宽字符转换为多个短字符是一个难点,不过我们只要掌握到其中的要领,便可如鱼得水.
好吧,那就让我们开始吧.
这个是我们需要转化的多字节字符串:
char sText[20] = {"多字节字符串!OK!"};

我们需要知道转化后的宽字符需要多少个数组空间.虽然在这个里程里面,我们可以直接定义一个20*2宽字符的数组,并且事实上将运行得非常轻松愉快.但假如多字节字符串更多,达到上千个乃至上万个,我们将会发现其中浪费的内存将会越来越多.所以以多字节字符的个数的两倍作为宽字符数组下标的声明绝对不是一个好主意.所幸,我们能够确知所需要的数组空间。我们只需要将MultiByteToWideChar()的第四个形参设为-1,即可返回所需的短字符数组空间的个数:

DWORD dwNum = MultiByteToWideChar (CP_ACP, 0, sText, -1, NULL, 0);
    接下来,我们只需要分配响应的数组空间:
wchar_t *pwText;
pwText = new wchar_t[dwNum];
if(!pwText)
{ delete []pwText; }
接着,我们就可以着手进行转换了.在这里以转换成ASCII码做为例子:
MultiByteToWideChar (CP_ACP, 0, psText, -1, sText, dwSize);

最后,使用完毕当然要记得释放占用的内存:
delete []psText;
  
同理,宽字符转为多字节字符的代码如下:
wchar_t wText[20] = {L"宽字符转换实例!OK!"};
DWORD dwNum = WideCharToMultiByte(CP_OEMCP,NULL,lpcwszStr,-1,NULL,0,NULL,FALSE);
char *psText;
psText = new char[dwNum];
if(!psText)
{ delete []psText; }
WideCharToMultiByte (CP_OEMCP,NULL,lpcwszStr,-1,psText,dwNum,NULL,FALSE);
delete []psText;
   如果之前我们已经分配好空间,并且由于字符串较短,可以不理会浪费的空间,仅仅只是想简单地将短字符和宽字符相互转换,那有没有什么简便的方法呢?
     WIN32 API里没有符合这种要求的函数,但我们可以自己进行封装:
BOOL MByteToWChar(LPCSTR lpcszStr, LPWSTR lpwszStr, DWORD dwSize)
{
DWORD dwMinSize;
dwMinSize = MultiByteToWideChar (CP_ACP, 0, lpcszStr, -1, NULL, 0);
if(dwSize < dwMinSize)
{ return FALSE; }
MultiByteToWideChar (CP_ACP, 0, lpcszStr, -1, lpwszStr, dwMinSize);
return TRUE;
}

BOOL WCharToMByte(LPCWSTR lpcwszStr, LPSTR lpszStr, DWORD dwSize)
{
DWORD dwMinSize;
dwMinSize = WideCharToMultiByte(CP_OEMCP,NULL,lpcwszStr,-1,NULL,0,NULL,FALSE);
if(dwSize < dwMinSize)
{ return FALSE; }
WideCharToMultiByte(CP_OEMCP,NULL,lpcwszStr,-1,lpszStr,dwSize,NULL,FALSE);
return TRUE;
}
使用方法也很简单,示例如下:
wchar_t wText[10] = {L"函数示例"};
char sText[20]= {0};
WCharToMByte(wText,sText,sizeof(sText)/sizeof(sText[0]));
MByteToWChar(sText,wText,sizeof(wText)/sizeof(wText[0]));
这两个函数的缺点在于无法动态分配内存,在转换很长的字符串时可能会浪费较多内存空间;优点是,在不考虑浪

费空间的情况下转换较短字符串非常方便.

2.MultiByteToWideChar()函数乱码的问题
有的朋友可能已经发现,在标准的WinCE4.2或WinCE5.0 SDK模拟器下,这个函数都无法正常工作,其转换之后

的字符全是乱码.及时更改MultiByteToWideChar()参数也依然如此.
不过这个不是代码问题,其结症在于所定制的操作系统.如果我们定制的操作系统默认语言不是中文,也会出现这种情况.由于标准的SDK默认语言为英文,所以肯定会出现这个问题.而这个问题的解决,不能在简单地更改控制面板的"区域选项"的"默认语言",而是要在系统定制的时候,选择默认语言为"中文".

系统定制时选择默认语言的位置于:Platform -> Setting... -> locale -> default language ,选择"中文",然后编译即可.

Windows CE:不支持参数CodePage中的CP_UTF7和CP_UTF8的值,以及参数dwFlags中的WC_NO_BEST_FIT_CHARS值。
  速查:Windows NT 3.1、Windows 95以上、Windows CE 1.0以上,头文件:winnls.h;库文件:kernel32.lib。

利用此API进行编码转换

GB2312,BIG5,Unicode相互转换
  
//GB2312 转换成 Unicode:
wchar_t* GB2312ToUnicode(const char* szGBString)
{
        UINT nCodePage = 936; //GB2312
        int nLength=MultiByteToWideChar(nCodePage,0,szGBString,-1,NULL,0);
        wchar_t* pBuffer = new wchar_t[nLength+1];
        MultiByteToWideChar(nCodePage,0,szGBString,-1,pBuffer,nLength);
        pBuffer[nLength]=0;
        return pBuffer;
}
//BIG5 转换成 Unicode:
wchar_t* BIG5ToUnicode(const char* szBIG5String)
{
        UINT nCodePage = 950; //BIG5
        int nLength=MultiByteToWideChar(nCodePage,0,szBIG5String,-1,NULL,0);
        wchar_t* pBuffer = new wchar_t[nLength+1];
        MultiByteToWideChar(nCodePage,0,szBIG5String,-1,pBuffer,nLength);
        pBuffer[nLength]=0;
        return pBuffer;
}
//Unicode 转换成 GB2312:
char* UnicodeToGB2312(const wchar_t* szUnicodeString)
{
        UINT nCodePage = 936; //GB2312
        int nLength=WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,NULL,0,NULL,NULL);
        char* pBuffer=new char[nLength+1];
        WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,pBuffer,nLength,NULL,NULL);
        pBuffer[nLength]=0;
        return pBuffer;
}
//Unicode 转换成 BIG5:
char* UnicodeToBIG5(const wchar_t* szUnicodeString)

        UINT nCodePage = 950; //BIG5
        int nLength=WideCharToMultiByte(nCodePage,0,
szUnicodeString,-1,NULL,0,NULL,NULL);
        char* pBuffer=new char[nLength+1];
        WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,pBuffer,nLength,NULL,NULL);
        pBuffer[nLength]=0;
        return pBuffer;
}
//繁体中文BIG5 转换成 简体中文 GB2312
char* BIG5ToGB2312(const char* szBIG5String)
{
LCID lcid = MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),
SORT_CHINESE_PRC);
        wchar_t* szUnicodeBuff = BIG5ToUnicode(szBIG5String);
        char* szGB2312Buff = UnicodeToGB2312(szUnicodeBuff);
        int nLength = LCMapString(lcid,LCMAP_SIMPLIFIED_CHINESE, szGB2312Buff,-1,NULL,0);
        char* pBuffer = new char[nLength + 1];
        LCMapString(0x0804,LCMAP_SIMPLIFIED_CHINESE,szGB2312Buff,-1,pBuffer,nLength);
        pBuffer[nLength] = 0;
        delete[] szUnicodeBuff;
        delete[] szGB2312Buff;
        return pBuffer;
}

//简体中文 GB2312 转换成 繁体中文BIG5
char* GB2312ToBIG5(const char* szGBString)
{
LCID lcid = MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),
SORT_CHINESE_PRC);
        int nLength = LCMapString(lcid,LCMAP_TRADITIONAL_CHINESE,szGBString,-1,NULL,0);
        char* pBuffer=new char[nLength+1];
        LCMapString(lcid,LCMAP_TRADITIONAL_CHINESE,szGBString,-1,pBuffer,nLength);
        pBuffer[nLength]=0;
        wchar_t* pUnicodeBuff = GB2312ToUnicode(pBuffer);
        char* pBIG5Buff = UnicodeToBIG5(pUnicodeBuff);
        delete[] pBuffer;
        delete[] pUnicodeBuff;
        return pBIG5Buff;
}


VC++中通过MultiByteToWideChar将string|char*转换为wstring|wchar_t* -

将string|char*转换为wstring|wchar_t*的例子:
1、string转换为wstring:
string str=_T("翔翔糖糖");
int size=MultiByteToWideChar(CP_ACP,0,str.c_str(),-1,NULL,0);
wchar_t *ch=new wchar_t[size+1];
if(!MultiByteToWideChar(CP_ACP,0,str.c_str(),-1,ch,size))
{ return false;}

wstring wstr=ch;
2、char*转换为wchar_t*:
char *str=_T("翔翔糖糖");
int size=MultiByteToWideChar(CP_ACP,0,str,-1,NULL,0);
wchar_t *ch=new wchar_t[size+1];
if(!MultiByteToWideChar(CP_ACP,0,str,-1,ch,size))
{ return false;}
MultiByteToWideChar使用例子
char* OleDBCom::UnsignedShortToCharp(unsigned short *strU)
{
UINT nStrULength=WideCharToMultiByte(
CP_ACP,0,strU,-1,NULL,NULL,NULL,NULL);
LPSTR lpStr;
lpStr=(char*)malloc(nStrULength);
WideCharToMultiByte(CP_ACP,0,strU,-1,lpStr,nStrULength,NULL,NULL);
return lpStr;
}
unsigned short* OleDBCom::CharpToUnsignedShort(LPSTR str)
{
OLECHAR strU[255];
int nStatus=MultiByteToWideChar(CP_ACP,0,str,-1,strU,255);
return strU;
}
====================
HRESULT __fastcall AnsiToUnicode(LPCSTR pszA, LPOLESTR* ppszW)
{
   ULONG cCharacters;
   DWORD dwError;
   if (NULL == pszA)
   {
     *ppszW = NULL;
     return NOERROR;
   }
   cCharacters = strlen(pszA)+1;
   *ppszW = (LPOLESTR) CoTaskMemAlloc(cCharacters*2);
   if (NULL == *ppszW)
     return E_OUTOFMEMORY;
   if (0 == MultiByteToWideChar(CP_ACP, 0, pszA, cCharacters,
       *ppszW, cCharacters))
   {
     dwError = GetLastError();
     CoTaskMemFree(*ppszW);
     *ppszW = NULL;
     return HRESULT_FROM_WIN32(dwError);
   }
return NOERROR;
这里有个例子,
PWSTR pWideCharStr;
int nLenOfWideCharStr;
首先计算需要的宽字符串的字符数
nLenOfWideCharStr=MultiByteToWideChar(CP_ACP,0,pMultiByteStr,-1,NULL,0)
这里的pMultiByteStr是要转换的多字节字符。
给pWideCharStr分配内存块
pWideCharStr=HeapAlloc(GetProcessHeap(),0,nLenOfWideCharStr*sizeof(WCHAR));
然后把多字节字符串转换成宽字符串
MultiByteToWideChar(CP_ACP,0,pMultiByteStr,-1,pWideCharStr,nLenOfWideCharStr)

WideCharToMultiByte和MultiByteToWideChar函数的用法
为了支持Unicode编码,需要多字节与宽字节之间的相互转换。
这两个系统函数在使用时需要指定代码页,在实际应用过程中遇到乱码问题,
然后重新阅读《Windows核心编程》,总结出正确的用法。
WideCharToMultiByte的代码页用来标记与新转换的字符串相关的代码页。
MultiByteToWideChar的代码页用来标记与一个多字节字符串相关的代码页。
常用的代码页由CP_ACP和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    ];
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;
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;
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;
}

#include "stdafx.h"
#include "string.h"
#include "stdio.h"
#include "windows.h"
int main(int argc, char* argv[])
{
char temp[20];
int nLen;
LPWSTR name = L"CPU";
sprintf(temp,"CPU%02d",i);
nLen = MultiByteToWideChar(CP_ACP,0,temp,-1,NULL,0);
MultiByteToWideChar(CP_ACP,0,temp,-1,(LPWSTR)name,nLen);
WideCharToMultiByte(CP_ACP,0,(LPWSTR)name,-1, strs,100,NULL,NULL);
printf("good: %s \n",name);
return 0;
}
调试时,在MultiByteToWideChar处报错
MultiByteToWideChar 函数把一个字符串映射为一个宽字符串。被这个函数映射的字符串不必属于多字节字符集。

    返回值:
若该函数成功,且 cchMultiByte 为非零值,则返回值是写入由 lpWideCharStr 指向的缓冲区中的宽字符数。

若该函数成功,且 cchMultiByte 为零,则返回值是以宽字符为单位的缓冲区大小值。该缓冲区可以接收转换后的字符串。
若该函数失败,则返回值为FALSE,调用GetLastErro可获得补充的错误信息。


1   //---------------------------------------------------------------------------
   //函数输入Big5字符,返回Gb简体字符   //两次转换
    //---------------------------------------------------------------------------
    AnsiString __fastcall Big2Gb(AnsiString sBig)
    {
    char* pszBig5=NULL; //Big5编码的字符
    wchar_t* wszUnicode=NULL; //Unicode编码的字符
    char* pszGbt=NULL; //Gb编码的繁体字符
    char* pszGbs=NULL; //Gb编码的简体字符
    AnsiString sGb; //返回的字符串
    int iLen=0; //需要转换的字符数
    pszBig5=sBig.c_str(); //读入需要转换的字符参数
    //计算转换的字符数
    iLen=MultiByteToWideChar (950, 0, pszBig5, -1, NULL,0) ;
    //给wszUnicode分配内存
    wszUnicode=new wchar_t[iLen+1];
    //转换Big5码到Unicode码,使用了API函数MultiByteToWideChar
    MultiByteToWideChar (950, 0, pszBig5, -1, wszUnicode,iLen);
     //计算转换的字符数
    iLen=WideCharToMultiByte (936, 0, (PWSTR) wszUnicode, -1, NULL,0, NULL, NULL) ;
    //给pszGbt分配内存
    pszGbt=new char[iLen+1];
    //给pszGbs分配内存
    pszGbs=new char[iLen+1];
    //转换Unicode码到Gb码繁体,使用API函数WideCharToMultiByte
    WideCharToMultiByte (936, 0, (PWSTR) wszUnicode, -1, pszGbt,iLen, NULL, NULL) ;
    //转换Gb码繁体到Gb码简体,使用API函数LCMapString
    LCMapString(0x0804,LCMAP_SIMPLIFIED_CHINESE, pszGbt, -1, pszGbs, iLen);
    //返回Gb码简体字符
    sGb=pszGbs;
    //释放内存
    delete [] wszUnicode;
    delete [] pszGbt;
    delete [] pszGbs;
    return sGb;
    }
2   //---------------------------------------------------------------------------
//函数输入Gb字符,返回Big5字符    //两次转换
    //---------------------------------------------------------------------------
    AnsiString __fastcall Gb2Big(AnsiString sGb)
    {
    char* pszGbt=NULL; //Gb编码的繁体字符
    char* pszGbs=NULL; //Gb编码的简体字符
    wchar_t* wszUnicode=NULL; //Unicode编码的字符
    char* pszBig5=NULL; //Big5编码的字符
    AnsiString sBig5; //返回的字符串
    int iLen=0; //需要转换的字符数
    pszGbs=sGb.c_str(); //读入需要转换的字符参数
    //计算转换的字符数
    iLen=MultiByteToWideChar (936, 0, pszGbs, -1, NULL,0) ;
    //给pszGbt分配内存
    pszGbt=new char[iLen*2+1];
    //转换Gb码简体到Gb码繁体,使用API函数LCMapString
LCMapString(0)
要确保是在unicode环境下,才可使用WideCharToMultiByte

阅读(4676) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~