Window下Unicode字符与多字节字符的转换方法

第一个就是宽字符到多字节字符转换函数,函数原型如下:

int WideCharToMultiByte(
UINT CodePage,
DWORD dwFlags,
LPCWSTR lpWideCharStr,
int cchWideChar,
LPSTR lpMultiByteStr,
int cbMultiByte,
LPCSTR lpDefaultChar,
LPBOOL lpUsedDefaultChar
); 

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

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

我想最常用的应该是CP_ACP和CP_UTF8了,前者将宽字符转换为ANSI,后者转换为UTF8。

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
50221 5022250225
50227
5022952936
54936 57002到57011
65000(UTF7)
42(Symbol)
对于UTF8,dwFlags必须为0或WC_ERR_INVALID_CHARS,否则函数都将失败返回并设置错误码ERROR_INVALID_FLAGS,你可以调用GetLastError获得。

lpWideCharStr: 待转换的宽字符串。

cchWideChar: 待转换宽字符串的长度,-1表示转换到字符串结尾。

lpMultiByteStr: 接收转换后输出新串的缓冲区。

cbMultiByte: 输出缓冲区大小,如果为0,lpMultiByteStr将被忽略,函数将返回所需缓冲区大小而不使用lpMultiByteStr。

lpDefaultChar: 指向字符的指针, 在指定编码里找不到相应字符时使用此字符作为默认字符代替。 如果为NULL则使用系统默认字符。对于要求此参数为NULL的dwFlags而使用此参数,函数将失败返回并设置错误码ERROR_INVALID_PARAMETER。

lpUsedDefaultChar:开关变量的指针,用以表明是否使用过默认字符。对于要求此参数为NULL的dwFlags而使用此参数,函数将失败返回并设置错误码ERROR_INVALID_PARAMETER。lpDefaultChar和lpUsedDefaultChar都设为NULL,函数会更快一些。

返回值: 如果函数成功,且cbMultiByte非0,返回写入lpMultiByteStr的字节数(包括字符串结尾的null);cbMultiByte为0,则返回转换所需

字节数。函数失败,返回0。
注意:函数WideCharToMultiByte使用不当,会给影响程序的安全。调用此函数会很容易导致内存泄漏,因为lpWideCharStr指向的输入缓冲区大小是宽字符数,而lpMultiByteStr指向的输出缓冲区大小是字节数。为了避免内存泄漏,应确保为输出缓冲区指定合适的大小。我的方法是先使cbMultiByte为0调用WideCharToMultiByte一次以获得所需缓冲区大小,为缓冲区分配空间,然后再次调用WideCharToMultiByte填充缓冲区,详见下面的代码。另外,从Unicode UTF16向非Unicode字符集转换可能会导致数据丢失,因为该字符集可能无法找到表示特定Unicode数据的字符。

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);

第二个是多字节字符到宽字符转换函数,函数原型如下:

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
50221 5022250225
50227
5022952936
54936 57002到57011
65000(UTF7)
42(Symbol)
对于UTF8,dwFlags必须为0或MB_ERR_INVALID_CHARS,否则函数都将失败并返回错误码ERROR_INVALID_FLAGS。

以下函数我没用过,只简要说明之。

int GetTextCharset( HDC hdc );

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

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

时间: 2024-08-04 01:05:55

Window下Unicode字符与多字节字符的转换方法的相关文章

C语言中宽字符和多字节字符

C 语言原本是在英文环境中设计的,主要的字符集是7 位的ASCII 码.从此开始,8 位的byte(字节)变成最常见的字符编码单位,但是国际化软件必须能够表示不同的字符,而这些字符数量庞大,无法使用一个字节编码,于是世界上使用各式 各样多字节的字符编码集合已经有数十年了,比如用来表示"非拉丁字母"以及"非字母"的中.日.韩文字系统.在1994 年,"Normative Addendum 1"(基准增补一)的采用,让ISO C 可以标准化两种表示大

Unicode字符集与多字节字符集的比较

今天因为需求又要在Windows下读取目录和文件了,还好以前做过这方面的工作(见"在Linux下和Windows下遍历目录的方法及如何达成一致性操作",封装在Windows和Linux下读取目录和文件的操作函数),当然直接拿过来用了,可没想到在VS2012下编译的时候出现了以下错误: error C2664: 'FindFirstFileW' : cannot convert parameter 1 from 'char [512]' to 'LPCWSTR' 定位错误源,指针移到错误

C++多字节字符转换为宽字符的两种方法

  目前知道有两种方式:可以提供宽字符与ANSI字符之间的转换, 第一种由COM库提供的函数 char*  _com_util::ConvertBSTRToString(BSTR ); BSTR _com_util::ConvertStringToBSTR(char*); Example // ConvertBSTRToString.cpp #include <comutil.h> #include <stdio.h> #pragma comment(lib, "coms

js实现控制textarea输入字符串的个数,鼠标按下抬起判断输入字符数_javascript技巧

[Html代码] <table> <tr> <td width="150">短信内容:</td> <td> <textarea name="message" cols="96" rows="5" onKeyDown="textCounter(message,remLen,65);" onKeyUp="textCounter(mess

C++多字节字符与宽字节字符相互转换_C 语言

最近在C++编程中经常遇到需要多字节字符与宽字节字符相互转换的问题,一直自己贴那几句代码.觉得麻烦,于是就自己写了一个类来封装wchar_t与char类型间的转换,其他的,诸如:CString\ LPWSTR\TCHAR CHAR\LPSTR之间也是一样用 复制代码 代码如下: #include <iostream> using namespace std; class CUser { public: CUser(); virtual~ CUser(); char* WcharToChar(w

c语言基础-C语言问题,关于如何把window下编程 变成Linux中的换行

问题描述 C语言问题,关于如何把window下编程 变成Linux中的换行 本机运行正确, 但是wrong answer. 个人认为应该是 的问题,求大神指点 C语言问题,关于如何把window下编程 变成Linux中的换行 Description 给出一个字符串str和一个字符ch,如果字符串str含有字符ch,就从该字符首次出现的位置开始,输出字符串中的字符至结束.如果字符串str不含字符ch,则输出"Not Found".(注意首字母大写) Input 多测试用例. 每个测试用例

Window下adb shell中文乱码问题解决方法_Android

Window下,进行adb shell后,举个例子,如果你的sdcard下保存着中文字符文件名的文件,则在CMD下显示是一些无规律的中文并夹杂着乱码. 出现这种情况的原因是: Android中使用的是UTF-8字符,而CMD默认字符集是ANSI,中文环境下即为GBK,代码页为936.查询当前代码页的方法为在CMD下直接输入"chcp"命令,并会返回"活动的代码页:936"字样.找出原因了,解决办法也就有了. 只要使用UTF-8格式的代码页65001就OK了,命令如下

Window下adb shell中文乱码问题解决方法

Window下,进行adb shell后,举个例子,如果你的sdcard下保存着中文字符文件名的文件,则在CMD下显示是一些无规律的中文并夹杂着乱码. 出现这种情况的原因是: Android中使用的是UTF-8字符,而CMD默认字符集是ANSI,中文环境下即为GBK,代码页为936.查询当前代码页的方法为在CMD下直接输入"chcp"命令,并会返回"活动的代码页:936"字样.找出原因了,解决办法也就有了. 只要使用UTF-8格式的代码页65001就OK了,命令如下

打印字符不全 打印字符不清晰

打印字符不全打印字符不清晰 对于喷墨打印机,可能有两方面原因,墨盒墨尽.打印机长时间不用或受日光直射而导致喷嘴堵塞. 解决方法是可以换新墨盒或注墨水,如果墨盒未用完,可以断定是喷嘴堵塞: 取下墨盒(对于墨盒喷嘴不是一体的打印机,需要取下喷嘴),把喷嘴放在温水中浸泡一会儿,注意一定不要把电路板部分浸在水中,否则后果不堪设想. 对于针式打印机,可能有以下几方面原因:打印色带使用时间过长:打印头长时间没有清洗,脏物太多:打印头有断针:打印头驱动电路有故障. 解决方法是先调节一下打印头与打印辊间的间距,