VC++字符编码之间的转换

来源:互联网 发布:mac上如何新建文件夹 编辑:程序博客网 时间:2024/06/09 17:48


1、把一个字符串(单字节char、多字节均可)转换为宽字符(UTF-16编码,双字节表示,在VC++程序中若选择Unicode编码,则使用的是双字节wchar_t)

函数原型:

[cpp] view plaincopyprint?
  1. int MultiByteToWideChar(  
  2.   __in       UINT CodePage,  
  3.   __in       DWORD dwFlags,  
  4.   __in       LPCSTR lpMultiByteStr,  
  5.   __in       int cbMultiByte,  
  6.   __out_opt  LPWSTR lpWideCharStr,  
  7.   __in       int cchWideChar  
  8. );  

CodePage --- 指出转换中使用的代码页,我的理解是指出源字符串的编码方式,以便进行转换,取值主要有:CP_ACP(ANSI编码,ASCII)、CP_MACCP(Macintosh上的编码)、CP_OEMCP(OEM编码页,可以打乱数据并且不可逆)、CP_SYMBOL(Symbol code page (42),MSDN也没具体说明...)、CP_THREAD_ACP(当前线程的windows ANSI编码)、CP_UTF7(仅用于强制7位传输机制下)、CP_UTF8(多字节编码,如果UNICODE字符由2个字节表示,则编码成UTF-8很可能需要3个字节。而如果UNICODE字符由4个字节表示,则编码成UTF-8可能需要6个字节,注:实际表示ASCII字符的UNICODE字符,将会编码成1个字节,并且UTF-8表示与ASCII字符表示是一样的。所有其他的UNICODE字符转化成UTF-8将需要至少2个字节。)。

dwFlags --- 转换类型,我使用的时候,主要是char和utf8(3字节的)转换为wchar_t,所以直接将该参数置为0(对于以下编码页其值必须为0:50220、50221、50222、50225、50227、50229、57002 至 57011、65000 (UTF-7)、42 (Symbol)。对于UTF-8或者54936编码也 (GB18030,始于Windows Vista)须设为0或MB_ERR_INVALID_CHARS),未深究,其取值有MB_COMPOSITEMB_ERR_INVALID_CHARSMB_PRECOMPOSED(默认值)、MB_USEGLYPHCHARS

lpMultiByteStr --- 指向待转换字符串的指针。

cbMultiByte --- cbMultiByte所指字符串的长度,以字节为单位。该参数不能设为0。如果该字符串是null结尾的,则可取值为-1,此时将处理整个字符串,所以转换后的双字节串也是null结尾的;若该参数设置为一个正整数,则只处理该参数指定的若干个字符,如果这些字符中不包含null,则转换后的双字节串不是null结尾,返回的长度也不包含该字符。

lpWideCharStr --- 接收转换后字符串的字符串指针(双字节的)。

cchWideChar --- lpWideCharStr所指字符串的长度,以字符为单位,若设为0,则函数返回转换需要的空间大小,单位是字符,不对lpWideCharStr做任何处理。

返回值:若成功则返回写入lpMultiByteStr中的字符的个数;若cchWideChar若设为0,则函数返回转换需要的空间大小,单位是字符;若源字符串无效,则返回相应的错误代码。

MSDN上的几个例子:

[cpp] view plaincopyprint?
  1. /***************************/  
  2. /* ansi-unicode conversion */  
  3. /***************************/  
  4.   
  5. BOOL AnsiToUnicode16(CHAR *in_Src, WCHAR *out_Dst, INT in_MaxLen)  
  6. {  
  7.     /* locals */  
  8.     INT lv_Len;  
  9.   
  10.   // do NOT decrease maxlen for the eos  
  11.   if (in_MaxLen <= 0)  
  12.     return FALSE;  
  13.   
  14.   // let windows find out the meaning of ansi  
  15.   // - the SrcLen=-1 triggers MBTWC to add a eos to Dst and fails if MaxLen is too small.  
  16.   // - if SrcLen is specified then no eos is added  
  17.   // - if (SrcLen+1) is specified then the eos IS added  
  18.   lv_Len = MultiByteToWideChar(CP_ACP, 0, in_Src, -1, out_Dst, in_MaxLen);  
  19.   
  20.   // validate  
  21.   if (lv_Len < 0)  
  22.     lv_Len = 0;  
  23.   
  24.   // ensure eos, watch out for a full buffersize  
  25.   // - if the buffer is full without an eos then clear the output like MBTWC does  
  26.   //   in case of too small outputbuffer  
  27.   // - unfortunately there is no way to let MBTWC return shortened strings,  
  28.   //   if the outputbuffer is too small then it fails completely  
  29.   if (lv_Len < in_MaxLen)  
  30.     out_Dst[lv_Len] = 0;  
  31.   else if (out_Dst[in_MaxLen-1])  
  32.     out_Dst[0] = 0;  
  33.   
  34.   // done  
  35.   return TRUE;  
  36. }  
  37.   
  38.   
  39. BOOL AnsiToUnicode16L(CHAR *in_Src, INT in_SrcLen, WCHAR *out_Dst, INT in_MaxLen)  
  40. {  
  41.     /* locals */  
  42.     INT lv_Len;  
  43.   
  44.   
  45.   // do NOT decrease maxlen for the eos  
  46.   if (in_MaxLen <= 0)  
  47.     return FALSE;  
  48.   
  49.   // let windows find out the meaning of ansi  
  50.   // - the SrcLen=-1 triggers MBTWC to add a eos to Dst and fails if MaxLen is too small.  
  51.   // - if SrcLen is specified then no eos is added  
  52.   // - if (SrcLen+1) is specified then the eos IS added  
  53.   lv_Len = MultiByteToWideChar(CP_ACP, 0, in_Src, in_SrcLen, out_Dst, in_MaxLen);  
  54.   
  55.   // validate  
  56.   if (lv_Len < 0)  
  57.     lv_Len = 0;  
  58.   
  59.   // ensure eos, watch out for a full buffersize  
  60.   // - if the buffer is full without an eos then clear the output like MBTWC does  
  61.   //   in case of too small outputbuffer  
  62.   // - unfortunately there is no way to let MBTWC return shortened strings,  
  63.   //   if the outputbuffer is too small then it fails completely  
  64.   if (lv_Len < in_MaxLen)  
  65.     out_Dst[lv_Len] = 0;  
  66.   else if (out_Dst[in_MaxLen-1])  
  67.     out_Dst[0] = 0;  
  68.   
  69.   // done  
  70.   return TRUE;  
  71. }  


2、把一个宽字符串(UTF-16编码,双字节表示)转换为多字节字符串(单字节char、多字节均可)

函数原型:

[cpp] view plaincopyprint?
  1. int WideCharToMultiByte(  
  2.   __in       UINT CodePage,  
  3.   __in       DWORD dwFlags,  
  4.   __in       LPCWSTR lpWideCharStr,  
  5.   __in       int cchWideChar,  
  6.   __out_opt  LPSTR lpMultiByteStr,  
  7.   __in       int cbMultiByte,  
  8.   __in_opt   LPCSTR lpDefaultChar,  
  9.   __out_opt  LPBOOL lpUsedDefaultChar  
  10. );  

前6个参数同上,对于最后两个参数:

lpDefaultChar --- 若转换后的字符是目标字符集无法表示的,则用该字符代替,若设为NULL,则使用系统默认的字符(对于CP_UTF7和CP_UTF8,必须为NULL)。

lpUsedDefaultChar --- 这是一个输出参数,一个指示函数是否使用了默认字符来代替无法表示的字符的标志的指针(对于CP_UTF7和CP_UTF8,必须为NULL),若值为TRUE则表明存在无法表示的字符,反之则为FALSE;该参数可设为NULL。

lpDefaultChar                lpUsedDefaultChar                Result

NULL                             NULL                                     不做任何检查,此时函数效率最高

非空字符                        NULL                                     使用用户指出的替代字符,但不设置lpUsedDefaultChar

NULL                            非空字符                                 使用系统默认替代字符,必要时设置lpUsedDefaultChar

非空字符                       非空字符                                 使用用户指出的替代字符,必要时设置lpUsedDefaultChar

0 0
原创粉丝点击