继上集故事《多字符集(ANSI)和UNICODE及字符串处理方式准则 》,我们现在有一些特殊需求:

有时候我们的字符串是多字符型,我们却需要使用宽字符型;有的时候却恰恰相反。

Windows为我们提供了这样的函数来处理这个问题:

1.MultiByteToWideChar

函数功能: 该函数映射一个字符串到一个宽字符 (unicode)的字符串。由该函数映射的字符串没必要是多字节字符组。

函数原型: int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cchMultiByte,

LPWSTR lpWideCharStr, int cchWideChar);

参数:

CodePage:指定执行转换的代码页,这个参数可以为系统已安装或有效的任何代码页所给定的值。你也 可以指定其为下面的任意一值:

CP_ACP:ANSI代码页;CP_MACCP:Macintosh代码 页;CP_OEMCP:OEM代码页;

CP_SYMBOL:符号代码页(42);CP_THREAD_ACP:当前线程ANSI代码 页;

CP_UTF7:使用UTF-7转换;CP_UTF8:使用UTF-8转换。

dwFlags:一组位标记用以指出是否未转换成预作或宽字符(若组合形式存在),是否使用象 形文字替代控制字符,以及如何处理无效字符。你可以指定下面是标记常量的组合,含义如下:

MB_PRECOMPOSED:通常使用预作字符——就是说,由一个基本字符和一个非空字符组 成的字符只有一个单一的字符值。这是缺省的转换选择。不能与

MB_COMPOSITE值一起使用。

MB_COMPOSITE:通常使用组合字符——就是说,由一个基本字符和一个非空字符组成的 字符分别有不同的字符值。不能与MB_PRECOMPOSED值一起使用。

MB_ERR_INVALID_CHARS:如果函数遇到无效的输入字符,它将运行失败,且 GetLastErro返回ERROR_NO_UNICODE_TRANSLATION值。

MB_USEGLYPHCHARS:使用象形文字替代控制字符。

组合字符由一个基础字符和一个非空字符构成,每一个都有不同的字符值。每个预作字符都有单一的 字符值给基础/非空字符的组成。在字符è中,e就是基础字符,而重音符标记就是非空字符。

函数的缺省动作是转换成预作的形式。如果预作的形式不存在,函数将尝试转换成组合形式。

标记MB_PRECOMPOSED和MB_COMPOSITE是互斥的,而标记 MB_USEGLYPHCHARS和MB_ERR_INVALID_CHARS则不管其它标记如何都可以设置。

lpMultiByteStr:指向将被转换字符串的字符。

cchMultiByte:指定由参数lpMultiByteStr指向的字符串中字节的个 数。如果这个值为-1,字符串将被设定为以NULL为结束符的字符串,并且自动计算长度。

lpWideCharStr:指向接收被转换字符串的缓冲区。

cchWideChar:指定由参数lpWideCharStr指向的缓冲区的字节个数。若此 值为零,函数返回缓冲区所必需的宽字符数,在这种情况下,lpWideCharStr中的缓冲区不被使用。

返回值

如果函数运行成功,并且cchWideChar不为零,返回值是由lpWideCharStr指向的缓 冲区中写入的宽字符数;如果函数运行成功,并且cchMultiByte为零,返回值是接收到待转换字符串的缓冲区所需求的宽字符数大小。如果函数运行失 败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。它可以返回下面所列错误代码:

ERROR_INSUFFICIENT_BUFFER;ERROR_INVALID_FLAGS;

ERROR_INVALID_PARAMETER;ERROR_NO_UNICODE_TRANSLATION。

注意

指针lpMultiByteStr和lpWideCharStr必须不一样。如果一样,函数将失 败,GetLastError将返回ERROR_INVALID_PARAMETER的值。

如果MB_ERR_INVALID_CHARS被设置并且在资源字符串中遇到无效的字符时,函 数将失败。如果MB_ERR_INVALID_CHARS不被设置,或是DBCS串中发现了头字节而没有有效的尾字节,无效字符将转换为缺省字符,但不是 资源字符串中的缺省字符。当无效字符被发现,且MB_ERR_INVALID_CHARS值被设置,函数返回零,GetLastErro显示 ERROR_NO_UNICODE_TRANSLATION的出错信息。

2.WideCharToMultiByte

函数功能: 该函数映射一个unicode字符串到一个多字节字符串。

函数原型: int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPWSTR lpWideCharStr, int cchWideChar, LPCSTR lpMultiByteStr, int cchMultiByte, LPCSTR lpDefaultChar, PBOOL pfUsedDefaultChar );

参数:

CodePage:指定执行转换的代码页,这个参数可以为系统已安装或有效的任 何代码页所给定的值。你也可以指定其为下面的任意一值:

CP_ACP:ANSI代码页;CP_MACCP:Macintosh代码 页;CP_OEMCP:OEM代码页;

CP_SYMBOL:符号代码页(42);CP_THREAD_ACP:当前线索ANSI代码 页;

CP_UTF7:使用UTF-7转换;CP_UTF8:使用UTF-8转换。

dwFlags [in] Specifies the handling of unmapped characters. The function performs more quickly when none of these flags is set. The following flag constants are defined.

Value

Meaning

WC_NO_BEST_FIT_CHARS

Windows 98/Me and Windows 2000/XP: Any Unicode characters that do not translate directly to multibyte equivalents are translated to the default character (see lpDefaultChar parameter). In other words, if translating from Unicode to multibyte and back to Unicode again does not yield the exact same Unicode character, the default character is used. This flag can be used by itself or in combination with the other dwFlag options.

WC_COMPOSITECHECK

Convert composite characters to precomposed characters.

WC_DISCARDNS

Discard nonspacing characters during conversion.

WC_SEPCHARS

Generate separate characters during conversion. This is the default conversion behavior.

WC_DEFAULTCHAR

Replace exceptions with the default character during conversion.

When WC_COMPOSITECHECK is specified, the function converts composite characters to precomposed characters. A composite character consists of a base character and a nonspacing character, each having different character values. A precomposed character has a single character value for a base/nonspacing character combination. In the character , the e is the base character, and the accent grave mark is the nonspacing character.

When an application specifies WC_COMPOSITECHECK, it can use the last three flags in this list (WC_DISCARDNS, WC_SEPCHARS, and WC_DEFAULTCHAR) to customize the conversion to precomposed characters. These flags determine the function's behavior when there is no precomposed mapping for a base/nonspace character combination in a wide-character string. These last three flags can only be used if the WC_COMPOSITECHECK flag is set.

The function's default behavior is to generate separate characters (WC_SEPCHARS) for unmapped composite characters.

For the code pages in the following table, dwFlags must be zero, otherwise the function fails with ERROR_INVALID_FLAGS.

50220 50221

50222

50225

50227 50229

52936

54936

57002 through 57011 65000 (UTF7)

65001 (UTF8)

42 (Symbol)

相关变量

lpWideCharStr:指向将被转换的unicode字符串。

cchWideChar:指定由参数lpWideCharStr指向的缓冲区的 字符个数。如果这个值为-1,字符串将被设定为以NULL为结束符的字符串,并且自动计算长度。

lpMultiByteStr:指向接收被转换字符串的缓冲区。

cchMultiByte:指定由参数lpMultiByteStr指向的缓冲 区最大值(用字节来计量)。若此值为零,函数返回lpMultiByteStr指向的目标缓冲区所必需的字节数,在这种情况 下,lpMultiByteStr参数通常为NULL。

lpDefaultChar和pfUsedDefaultChar: 只有当WideCharToMultiByte函数遇到一个宽字节字符,而该字符在uCodePage参数标识的代码页中并没有它的表示法 时,WideCharToMultiByte函数才使用这两个参数。如果宽字节字符不能被转换,该函数便使用lpDefaultChar参数指向的字符。 如果该参数是NULL(这是大多数情况下的参数值),那么该函数使用系统的默认字符。该默认字符通常是个问号。这对于文件名来说是危险的,因为问号是个通 配符。pfUsedDefaultChar参数指向一个布尔变量,如果Unicode字符串中至少有一个字符不能转换成等价多字节字符,那么函数就将该变 量置为TRUE。如果所有字符均被成功地转换,那么该函数就将该变量置为FALSE。当函数返回以便检查宽字节字符串是否被成功地转换后,可以测试该变 量。

返回值: 如果函数运行成功,并且cchMultiByte不为零,返回值是由 lpMultiByteStr指向的缓冲区中写入的字节数;如果函数运行成功,并且cchMultiByte为零,返回值是接收到待转换字符串的缓冲区所 必需的字节数。如果函数运行失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。它可以返回下面所列错误代码:

ERROR_INSUFFICIENT_BJFFER;ERROR_INVALID_FLAGS;

ERROR_INVALID_PARAMETER;ERROR_NO_UNICODE_TRANSLATION。

注意: 指针lpMultiByteStr和lpWideCharStr必须不一样。如果一样, 函数将失败,GetLastError将返回ERROR_INVALID_PARAMETER的值。

除此之外,还有几个比较有意思的字符串处理函数:

1.GetTextCharsetInfo

函数功能: 返回关于选入指定的设备描述表内的当前字体信息。

函数原型

int GetTextCharsetInfo( 
__in HDC hdc, 
__out LPFONTSIGNATURE lpSig, 
__in DWORD dwFlags 
);

参数

hdc [in] 设备描述表的句柄。

lpSig [out] 可选。指向一个 FONTSIGNATURE 数据结构的指针,该指针接收字体签名信息。

如果一个 True Type 字体被选入当前的设别描述表,结构会接收能够标识编码页和Unicode 子范围的字体符号。

如果字体不是 True Type ,则结构会接收到0.此时,应用程序应使用 TranslateCharsetInfo 函数来获得原始的字体签名。

如果应用程序不需要 FONTSIGNATURE 信息时,可以将该参数设为NULL。此时,应用程序也可以调用GetTextCharset 函数,而且调用该函数与调用GetTextCharset函数是一个效果。

dwFlags [in] 保留。必须为0.

返回值

如果超过,返回一个值用来标识选入设备描述表内的字体的字符集信息。如果函数失败,返回值是  DEFAULT_CHARSET.

2.GetTextCharset 
函数功能:
 此函数获取当前选进的设备描述表的字符集,等同于GetTextCharsetInfo(hdc,   NULL,   0)。

函数原型: int   GetTextCharset(   HDC   hdc   );

返回值:   成功返回字符集标识,失败返回DEFAULT_CHARSET。

3.BOOL   IsDBCSLeadByte(   BYTE   TestChar   ); 
此函数使用当前WindowsANSI代码页判断指定字节是不是一个潜在的双字节字符(DBCS)的引导字节。若使用其他代码页,请用

IsDBCSLeadByteEx函数。

4.BOOL   IsDBCSLeadByteEx( UINT   CodePage, BYTE   TestChar ); 
此函数判断指定字节是不是一个潜在的双字节字符(DBCS)的引导字节。 
CodePage可用的值有:CP_ACP,CP_MACCP,CP_OEMCP,CP_THREAD_ACP。

5. BOOL   IsTextUnicode( CONST   VOID*   pBuffer, int   cb, LPINT   lpi ); 
此函数判断指定缓冲区里是否可能会有某种格式的Unicode文本。这个函数判断方式并不准确,所以可能会返回错误结果。记事本就是使用

了这个函数,所以有时候会出现乱码。所以请谨慎使用这个函数。

还有三个Windows不推荐使用的函数:NlsDllCodePageTranslation,UnicodeToBytes和BytesToUnicode,此处不作过多介绍了。

其中,我们重点关注的还是MultiByteToWideChar和WideCharToMultiByte这两个函数,具体这两个函数的使用方式,

请关注下集故事《让你的程序更加适用——使用ANSI和UNICODE导出函数》

同系列文章参看:

《多字符集(ANSI)和UNICODE及字符串处理方式准则》

 

《 让你的程序更加适用——使用ANSI和UNICODE导出函数 》

http://blog.csdn.net/blpluto/article/details/5755320

-----------------------------------------------------------------------------------------------------------------

继前两篇文章之后,我们更加关心的问题是,我们可能为了方便他人的使用,需要提供ANSI和UNICODE版本的函数,此时,我们可以模

仿 Windows的作法,我们只编写UNICODE版本的函数,然后在ANSI版本的函数中,我们把多字符转换成UNICODE字符串,然后调用UNICODE版

本 的函数,完成之后,再把他还原成多字符集的字符串。

此处,引用示例,逆转字符串中所有字符的函数:

  1. BOOL StringReverseW(PWSTR pWideCharStr, DWORD cchLength)
  2. {
  3. PWSTR pEndOfStr = pWideCharStr + wcsnlen_s(pWideCharStr, cchLength) - 1;
  4. wchar_t cCharT;
  5. while(pWideCharStr < pEndOfStr)
  6. {
  7. //保存到一个临时变量中
  8. cCharT = *pWideCharStr;
  9. //把最后一个字符放进第一个字符中
  10. *pWideCharStr = *pEndOfStr;
  11. //把临时变量放进最后一个字符中
  12. *pEndOfStr = cCharT;
  13. //想左移动一个字符位置
  14. pWideCharStr++;
  15. //向右移动一个字符位置
  16. pEndOfStr--;
  17. }
  18. return TRUE;
  19. }
  20. BOOL StringReverseA(PSTR pMultiByteStr, DWORD cchLength)
  21. {
  22. PWSTR pWideCharStr;
  23. int   nLenOfWideCharStr;
  24. BOOL  fOk = FALSE;
  25. //获取需要转换字符串的大小
  26. nLenOfWideCharStr = MultiByteToWideChar(CP_ACP, 0,
  27. pMultiByteStr, cchLength, NULL, 0);
  28. //为字符串分配内存
  29. pWideCharStr = (PWSTR)HeapAlloc(GetProcessHeap(), 0,
  30. nLenOfWideCharStr * sizeof(wchar_t));
  31. if (NULL == pWideCharStr)
  32. {
  33. return fOk;
  34. }
  35. //转换成宽字符pWideCharStr
  36. MultiByteToWideChar(CP_ACP, 0, pMultiByteStr, cchLength,
  37. pWideCharStr, nLenOfWideCharStr);
  38. //使用宽字符函数进行处理
  39. fOk = StringReverseW(pWideCharStr, cchLength);
  40. if (fOk)
  41. {
  42. //转换为多字符
  43. WideCharToMultiByte(CP_ACP, 0, pWideCharStr, cchLength,
  44. pMultiByteStr, (int)strlen(pMultiByteStr), NULL, NULL);
  45. }
  46. //释放内存
  47. HeapFree(GetProcessHeap(), 0, pWideCharStr);
  48. return fOk;
  49. }

 

然后,我们可以在发布的.h头文件中,这样定义函数:

  1. BOOL StringReverseW(PWSTR pWideCharStr, DWORD cchLength)
  2. BOOL StringReverseA(PSTR pMultiByteStr, DWORD cchLength)
  3. #ifdef UNICODE
  4. #define StringReverse StringReverseW
  5. #else
  6. #define StringReverse StringReverseA
  7. #endif



这样,使用我们函数的人,也就不用再为是否是UNICODE或是ANSI而焦头烂额了。

http://blog.csdn.net/blpluto/article/details/5755358

UNICODE和ANSI字符串的转换(解释了MultiByteToWideChar,WideCharToMultiByte,GetTextCharsetInfo,GetTextCharset,IsDBCSLeadByte,IsDBCSLeadByteEx,IsTextUnicode一共7个函数)的更多相关文章

  1. 字符编码(续)---Unicode与ANSI字符串转换以及分辨字符编码形式

    Unicode与ANSI字符串转换 我们使用windows函数MultiByteToWideChar将多字节字符串转换为宽字符字符串,如下: int MultiByteToWideChar( UINT ...

  2. Python: 在Unicode和普通字符串之间转换

    Unicode字符串可以用多种方式编码为普通字符串, 依照你所选择的编码(encoding): <!-- Inject Script Filtered --> Toggle line nu ...

  3. Python——在Unicode和普通字符串之间转换

    1.1. 问题 Problem You need to deal with data that doesn't fit in the ASCII character set. 你需要处理不适合用ASC ...

  4. iOS-NSString值为Unicode格式(字符串编码转换成中文编码)

    + (NSString *)replaceUnicode:(NSString *)unicodeStr  {             NSString *tempStr1 = [unicodeStrs ...

  5. 有关UNICODE、ANSI字符集和相关字符串操作

    Q UNICODE字符串如何显示 A 如果程序定义了_UNICODE宏直接用 WCHAR *str=L"unicodestring"; TextOut(0,0,str); 否则就需 ...

  6. UNICODE与ANSI的区别

    什么是ANSI,什么又是UNICODE呢?其实这是两种不同的编码方式标准,ANSI中的字符采用8bit,而UNICODE中的字符采用16bit.(对于字符来说ANSI以单字节存放英文字符,以双字节存放 ...

  7. Ansi、Unicode、UTF8字符串之间的转换和写入文本文件

    转载请注明出处http://www.cppblog.com/greatws/archive/2008/08/31/60546.html 最近有人问我关于这个的问题,就此写一篇blog Ansi字符串我 ...

  8. UNICODE字符串与多字节字符串的转换

    相互转换的两个函数的声明: 1. 多字节字符串与宽字符串的转换 int MultiByteToWideChar( UINT CodePage, // code page,一般设为 CP_ACP DWO ...

  9. Windows下ANSI、Unicode、UTF8字符编码转换

    主意:输入字符串必须是以'\0'结尾,如果输入字符串没有以'\0'结尾,请手动设置,否则转换会有错误. unsigned int EncodeUtil::AnsiToUcs2( char* pAnsi ...

随机推荐

  1. AFNetworking2.5使用2

    链接地址:http://blog.csdn.net/abc4715760/article/details/46521111 官网下载2.5版本:http://afnetworking.com/ 此文章 ...

  2. SuperSocket源码解析之启动过程

    一 简介 这里主要说明从配置系统引导启动SuperScoekt作为应用程序,且以控制台程序方式启动 二 启动过程 2.1 配置解析 从读取配置文件开始,直接拿到一个SocketServiceConfi ...

  3. 利用Java内置的API开发JMX功能

    一.什么是JMX JMS是一种Java规范,定义了如何管理一个软件系统(或应用程序)的规范. 对于一个简单的应用程序,该程序本身不需要被管理.但如果是开发的一个复杂系统(如一个电商平台.一个企业内部管 ...

  4. 【HTML5游戏开发小技巧】RPG情景对话中,令文本逐字输出

    以前用JAVAscript实现过令文本逐字输出的效果,今天我来用html5中的canvas实现一下.canvas里的内容可不像<p>那样好操作,首先,你需要懂得一些html5的API才能操 ...

  5. JAVA多态学习3

    这一节我们来学习抽象类 抽象类–深入讨论 抽象类是java中一个比較重要的类. 1.用abstract关键字来修饰一个类时.这个类就是抽象类. 2.用abstract关键字来修饰一个方法时,这种方法就 ...

  6. 饭卡(HDOJ2546)

    饭卡 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submiss ...

  7. wcf 出现 IsContentTypeSupported 错误

    查看添加的服务地址是不是https开头的,而 *.config 文件里面自动添加的链接变成了http,当前的bindbing类型为basicHttpBinding, 解决方法:在config文件里面手 ...

  8. WCF技术剖析之二十一:WCF基本异常处理模式[中篇]

    原文:WCF技术剖析之二十一:WCF基本异常处理模式[中篇] 通过WCF基本的异常处理模式[上篇], 我们知道了:在默认的情况下,服务端在执行某个服务操作时抛出的异常(在这里指非FaultExcept ...

  9. mysql数据导出权限问题

    mysql数据导出的方法有非常多,比如mysqldump, mysql -e 'sql' > file, 这些都能够非常方便的导出数据,但是在使用普通用户导出数据的时候,出现了问题. 1 sel ...

  10. 【SICP感应】3 级数据和符号数据

    在本书的第二章学习时,有一个问题我一直很困扰,那是2.2.4举例节.因为没有华丽的输出模式书,它只能有一个对的英文字母.两三个月的这浅浅的学校前Common Lisp同样是真实的,当.了非常赞的线条, ...