Unicode 与 ANSI 字符串转换

如果你经常在 Windows 平台下写程序的话,我相信你一定会遇到 Unicode 与 ANSI 字符串之间的转换(string <-> CString之类的)。


要想实现 Unicode 和 ANSI 之间的转换,我之前的一篇文章中简单的介绍了一下:VS 系列 CString 转 string 方法,其实文中的方法是我蒙出来的,简单有效,至于原理我也不甚明了。大部分人使用的是以下两种函数来实现两者的转换:


1) ANSI -> Unicode

int  MultiByteToWideChar(
   __in   UINT  CodePage, // 标识了与多字节关联的一个代码页值
   __in   DWORD  dwFlags, // 允许我们进行额外的控制,它会影响带变音符号(比如重音)的字符。但是一般情况下不适用,赋为 0 即可。
   __in   LPCSTR  lpMultiByteStr, // 参数指定要转换的字符串
   __in   int  cbMultiByte,       // 指定要转换串长度的长度(字节数),如果参数值是-1,函数便可自动判断源字符串的长度
   __out  LPWSTR  lpWideCharStr,  // 指定转换后Unicode版本的字符串内存地址
   __in   int  cchWideChar        // 指定 lpWideCharStr 缓冲区的最大长度。
                                 // 如果传入0,函数不会进行转换,而是返回一个宽字符数(包括终止字符'\0'),
                 // 只有当缓冲区能够容纳该数量的宽字符时,转换才会成功。
);

转换步骤:

(1)调用 MultiByteToWideChar,为 pWideCharStr 参数传入 NULL, 为cchWideChar 参数传入 0,为 cbMultiByte 参数传入 -1 

(2)分配一块足以容纳转换后的 Unicode 字符串的内容。它的大小是上一个 MultiByteToWideChar 调用的返回值乘以 sizeof(wchar_t) 

(3)再次调用MultiByteToWideChar,这一次将缓冲区地址作为 pWideCharStr 参数的值传入,将第一次 MultiByteToWideChar 调用的返回值乘以 sizeof(wchar_t) 后得到大小作为 cchWideChar 参数的值传入。

(4)使用转换后的字符串

(5)释放 Unicode 字符串占用的内存块。


示例代码:

/*
  * Subject: Convert ANSI to Unicode
  * IDE: Visual Studio 2008
  * Auther: http://www.cnblogs.com/chinazhangjie
  * Mail: chinajiezhang@gmail.com
  * Date:2011/10/10
  */
 
#include <stdio.h>
#include <windows.h>
 
int  main()
{
     char  *pANSI = "ANSI to Unicode, ANSI 转换到 Unicode" ;
     wchar_t  *pUnicode = NULL;
     int  nWideCharLen = 0;
 
     // step.1
     nWideCharLen = MultiByteToWideChar(CP_ACP, 0, pANSI, -1, NULL, 0);
     printf ( "nWideCharLen = %d\n" , nWideCharLen);
 
     // step.2
     pUnicode = ( wchar_t *) malloc (nWideCharLen * sizeof ( wchar_t ));
 
     // step.3
     MultiByteToWideChar(CP_ACP, 0, pANSI, -1, pUnicode, nWideCharLen * sizeof ( wchar_t ));
 
     // step.4
     MessageBoxW(NULL, pUnicode, TEXT( "Unicode" ), 0);
 
     // step.5
     free (pUnicode);
 
     return  0;
}

2) Unicode->ANSI

int  WideCharToMultiByte(
   __in   UINT  CodePage,   // 标志了要与新转换的字符串关联的代码页
   __in   DWORD  dwFlags,   // 制定额外的转换控制,一般不需要进行这种程度的控制,而为 dwFlag 传入 0
   __in   LPCWSTR  lpWideCharStr, // 指定要转换的字符串的内存地址
   __in   int  cchWideChar,       // 指出该字符串的长度,如果传入 -1 ,则由函数来判断字符串的长度
   __out  LPSTR  lpMultiByteStr,  // 转换后的缓冲区
   __in   int  cbMultiByte,       // 指定 lpMultiByteStr 缓冲区的最大大小(字节数),如果传入 0 ,函数返回该目标缓冲区需要的大小
   __in   LPCSTR  lpDefaultChar, 
   __out  LPBOOL  lpUsedDefaultChar // 宽字符字符串中,如果至少有一个字符不能转换为对应的多字节形式,函数就会把这个变量设为 TRUE 。如果所有字符都能成功转换,就会把这个变量设为 FALSE。 通常将此函数传入 NULL 值。
);


只有一个字符在 uCodePage 制定的代码页中没有对应的表示时,WideCharToMultiByte 才会使用后两个参数。在遇到一个不能转换的字符时,函数便使用 pDefaultChar 参数指向的字符。如果这个参数指向为 NULL ,函数就会使用一个默认的字符。这个默认的值通常是一个问号。这对文件操作是非常危险的,因为问号是一个通配符。


转换步骤和 ANSI -> Unicode 相似,故不做赘述。


示例代码:

/*
  * Subject: Convert Unicode to ANSI
  * IDE: Visual Studio 2008
  * Auther: http://www.cnblogs.com/chinazhangjie
  * Mail: chinajiezhang@gmail.com
  * Date:2011/10/10
  */
 
#include <stdio.h>
#include <windows.h>
 
int  main()
{
     wchar_t  *pUnicode = TEXT( "Convert Unicode to ANSI, Unicode 转换为 ANSI" );
     char     *pANSI    = NULL;
     int       nByte     = 0;
 
     // step.1
     nByte = WideCharToMultiByte(CP_ACP, 0, pUnicode, -1, NULL, 0, NULL, NULL);
 
     // step.2
     pANSI = ( char *) malloc (nByte);
 
     // step.3
     WideCharToMultiByte(CP_ACP, 0, pUnicode, -1, pANSI, nByte, NULL, NULL);
 
     // step.4
     printf_s( "ANSI = %s\n" , pANSI);
 
     // step.5
     free (pANSI);
 
     return  0;
}

/*******************************************************/
* 本文由 独酌逸醉 原创,转载请注明博客链接,谢谢!
  http://www.cnblogs.com/chinazhangjie/archive/2011/10/10/2205878.html
* 参考书籍:《Windows核心编程(第5版)》
* 时间:2011.10.10
/*******************************************************/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值