WideCharToMultiBye、MultiByteToWideChar函数

一、两个函数的介绍——这里的多字节是广义的,即可以ANSI编码,也可指UTF_8编码等

(一)WideCharToMultiBye——宽字符到多字节字符转换函数

1、函数原型如下

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

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

2、参数说明:

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

①CP_ACP 当前系统ANSI代码页 ——将宽字符转换为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 ——宽字符转换为UTF8

(2)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 50222 50225 50227 50229 5293654936 57002到57011 65000(UTF7)42(Symbol)

对于UTF8,dwFlags必须为0或WC_ERR_INVALID_CHARS,否则函数都将失败返回并设置错误码ERROR_INVALID_FLAGS,你可以调用GetLastError获得。  为了支持UNICODE编码,需要多字节与宽字节之间的相互转换。这两个系统函数在使用时需要指定代码页。

(3)lpWideCharStr: 待转换的宽字符串。

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

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

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

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

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

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

注意:函数WideCharToMultiByte使用不当,会给影响程序的安全。调用此函数会很容易导致内存泄漏,因为lpWideCharStr指向的输入缓冲区大小是宽字符数,而lpMultiByteStr指向的输出缓冲区大小是字节数。为了避免内存泄漏,应确保为输出缓冲区指定合适的大小。我的方法是先使cbMultiByte为0调用WideCharToMultiByte一次以获得所需缓冲区大小,为缓冲区分配空间,然后再次调用WideCharToMultiByte填充缓冲区,详见下面的代码。另外,从UnicodeUTF16向非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);

(二)MultiByteToWideChar——多字节字符到宽字符的转换函数

1、函数原型

int MultiByteToWideChar(
   UINT      CodePage,
   DWORD     dwFlags,
   LPCSTR    lpMultiByteStr,
   int       cbMultiByte,
   LPWSTR    lpWideCharStr,
   int       cchWideChar
);

2、参数说明:

(1)dwFlags: 指定是否转换成预制字符或合成的宽字符,对控制字符是否使用像形文字,以及怎样处理无效字符。

①MB_PRECOMPOSED 总是使用预制字符,即有单个预制字符时,就不会使用分解的基字符和不占空间字符。此为函数的默认选项,不能和MB_COMPOSITE合用。

②MB_COMPOSITE 总是使用分解字符,即总是使用基字符+不占空间字符的方式

③MB_ERR_INVALID_CHARS 设置此选项,函数遇到非法字符就失败并返回错误码ERROR_NO_UNICODE_TRANSLATION,否则丢弃非法字符

④MB_USEGLYPHCHARS 使用像形字符代替控制字符

对于下列代码页,dwFlags必须为0,否则函数返回错误码ERROR_INVALID_FLAGS。

50220 50221 50222 50225 50227 50229 5293654936 57002到57011 65000(UTF7)42(Symbol)

对于UTF8,dwFlags必须为0或MB_ERR_INVALID_CHARS,否则函数都将失败并返回错误码ERROR_INVALID_FLAGS。

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

int GetTextCharset( HDC hdc );

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

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

二、编程实验:常用的代码页由CP_ACP和CP_UTF8两个——使用CP_ACP代码页就实现了ANSI与Unicode之间的转换。使用CP_UTF8代码页就实现了UTF-8与Unicode之间的转换。

(一)ANSI to Unicode

wstring ANSIToUnicode( const string&str )

{
    intlen = 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;
}

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

}

(三) 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;
}

(四)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;
}
时间: 2024-11-03 22:14:21

WideCharToMultiBye、MultiByteToWideChar函数的相关文章

WideCharToMultiByte和MultiByteToWideChar函数的用法

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

关于多字节、宽字节、WideCharToMultiByte和MultiByteToWideChar函数的详解

所谓的短字符,就是用8bit来表示的字符,典型的应用是ASCII码. 而宽字符,顾名思义,就是用16bit表示的字符,典型的有UNICODE. ********************************第一个就是宽字符到多字节字符转换函数,函数原型如下: int WideCharToMultiByte( UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, in

char向wchar的转换-MultiByteToWideChar

问题产生 使用CreateFile函数,如下: CreateFile(lpcTheFile, GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) 第一个参数是wchar类型,而我从配置文件中读入的文件路径是char类型,因此涉及到char至wchar的转换问题 问题解决 使用MultiByteToWideChar函数函数代码如下: DWORD dwPathLen = MultiByteToWideChar(CP_ACP

MultiByteToWideChar和WideCharToMultiByte用法详解

今天写ini文件的时候发现的问题: TCHAR temp[128]; //strcpy_s(temp, request.newVersion); MultiByteToWideChar(CP_ACP, 0, request.newVersion, -1, temp, 100); WritePrivateProfileString(L"DeviceInfo", L"firmwareVersion", temp/*(LPCWSTR)request.newVersion*

C++中Cstring、wstring 和string互相转换总结

通过前一篇文章<C++中string,wstring,CString的基本概念和用法>,对Cstring.wstring 和string有了一个了解.string是C++提供的标准字符串操作类.wstring是操作宽字符串的类..CString是对string(字符串)和wstring(宽字符串)的一个封装,常用在mfc中,用来解决编码问题的.在编程过程中,经常会遇到Cstring.wstring 和string之间的相互转换,在这里做了个简单地总结,另外也会附上其他类型的转换.常见的转换方式

ANSI与Unicode的转换

最近遇到中文路径访问的问题,又重新学习了一遍ansi与Unicode的知识,博文记录下来以供后续参考. ANSI 编码 ANSI是一种字符代码,为使计算机支持更多语 言,通常使用0x80~0xFF 范围的2 个字节来表示1 个字符.不同的国家和地区制定了不同的标准,由此产生了GB2312.GBK.GB18030.Big5.Shift_JIS 等各自的编码标准. 这些使用多个字节来代表一个字符的各种汉字延伸编码方式,称为ANSI 编码. 关于MBCS字符集(Multi Byte Character

string 转 LPCTSTR

(1)在ANSI字符集下 LPCTSTR想当于LPCSTR,其中L指long,P指Point,C指Const.在程序中可以直接用char*类型的数据对LPCSTR进行赋值,用下述语句: LPCSTR a1= "abc"; string a2 = "abcde"; a1 = a2.c_str(); (2)在Unicode字符集下 LPCTSTR相当于LPCWSTR,它相当于wchar_t.可以用下述的语句对它进行赋值 LPCWSTR a1; wstring a2; a

VC常用数据类型使用转换

我们先定义一些常见类型变量借以说明 [cpp] view plain copy int i = 100; long l = 2001; float f=300.2; double d=12345.119; char username[]="赵三"; char temp[200]; char *buf; CString str; _variant_t v1; _bstr_t v2; 一.其它数据类型转换为字符串 短整型(int) [cpp] view plain copy itoa(i,

OpenGL入门学习

说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640*480分辨率.16色来做吗?显然是不行的. 本帖的目的是让大家放弃TC的老旧图形接口,让大家接触一些新事物. OpenGL作为当前主流的图形API之一,它在一些场合具有比DirectX更优越的特性. 1.与C语言紧密结合. OpenGL命令最初就是用C语言函数来进行描述的,对于学习过C语言的人来讲,OpenGL是容易理解和学习的