MultiByte与WideChar之间的转化

遇到这样一个问题,程序使用的是Unicode编码,从Edit中读取出来的Cstring内容直接存储到txt文件中会出现乱码。

txt使用的ANSI编码,而Edit空间中的内容是Unicode编码,所以会出现乱码。


百度一下才知道,编译器的库函数中存在Unicode与ANSI之间相互转化的函数。




1. ANSI转化为Unicode

MultiByteToWideChar 这个函数将ANSI转化为Unicode

原函数:

int MultiByteToWideChar(

UINT CodePage,

DWORD dwFlags,

LPCSTR lpMultiByteStr,

int cchMultiByte,

LPWSTR lpWideCharStr,

int cchWideChar

);

参数说明:

CodePage参数标识了与多字节字符串关联的一个代码页值。我自己理解就是要转化成的字符串的编码方式。

dwFlags参数允许我们进行额外的控制,它会影响带变音符号(比如重音)的字符,但是,一般情况下不使用这个标识,所以传给dwFlags的值是0。

lpMultiByteStr参数指定要转换的字符串。

cchMultiByte参数指定字符串的长度(字节数)。如果传给cchMultiByte的参数值是-1,函数便可自动判断源字符串的长度。

lpWideCharStr参数指定的是一个内存缓冲区的地址,缓冲区的内容是转换后的Unicode版本的字符串。

cchWideChar参数指定缓冲区的最大长度(字符数)

一般按照以下步骤将一个多字节字符串转化为Unicode形式

(1)调用MultiByteToWideChar,为lpWideCharStr参数传入NULL,为cchWideChar参数传入0,为cchMultiByte参数传入-1。

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

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

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

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

下面是一个简单的例子:

LPCSTR strMulti = "鎯呭喌?";
int iNum = MultiByteToWideChar(CP_UTF8, 0, strMulti, -1, NULL, 0);
LPWSTR pUniCode = new WCHAR[sizeof(wchar_t) * iNum];
MultiByteToWideChar(CP_UTF8, 0, strMulti, -1, pUniCode, sizeof(wchar_t) * iNum );
delete []pUniCode;

最后pUniCode的结果是UTF8编码的“情况?”




2. Unicode转化为ANSI

WideCharToMultiByte 这个函数将Unicode转化为ANSI

函数原型:

int WideCharToMultiByte(

UINT CodePage,

DWORD dwFlags,

LPCWSTR lpWideCharStr,

int cchWideChar,

LPSTR lpMultiByteStr,

int cchMultiByte,

LPCSTR lpDefaultChar,

LPBOOL pfUsedDefaultChar //至少有一个字符不能转换为其多字节形式,函数就会把这个变量设为TRUE

);


参数说明:

CodePage参数标识了要与新转换的字符串关联的代码页,代码页包含如下几个值:


dwFlags参数允许我们指定额外的转化控制,这些标志会影响带变音符号的字符和系统不能转换的字符。但是我们一般不需要这种转换,所以传入参数设置为0

lpWideCharStr参数指定要转换字符串的内存地址。

cchWideChar参数指出该字符串的长度(字符数),如果此参数传入-1,由函数来判断字符串的长度。

lpMultiByteStr参数指向转换后字符串的缓存区地址。

cchMultiByte参数中指定此缓存的最大值(字节数)。如果将其设置为0,将会返回目标缓存区需要的大小。

这个函数与上面函数的主要区别是,无需在进行乘法运算,它返回的目标缓存区的大小就是所需的字节数。

注意:此函数比上面的函数参数要多两个,分别是lpDefaultChar、pfUsedDefaultChar。只有一个字符在uCodePage指定的代码页中没有对应的表示时,WideCharToMultiByte函数才会使用这两个参数,在遇到一个不能转换的宽字符时,函数便使用lpDefaultChar参数指向的字符。如果这两个参数为NULL,函数会使用系统默认的字符。这个默认字符通常是一个问号。这对文件名来说非常危险,因为问号是一个通配符。pfUsedDefaultChar参数指向一个布尔变量,在宽字符字符串中,如果至少有一个字符不能转换为对应的多字节形式,函数就会把这个变量设置为TRUE,如果所有字符都能成功转化,就会把这个变量设置为FALSE,我们可以在函数返回后测试该变量,验证宽字符串是否已经转化成功,同样,我们可以通过此参数传入NULL值。

DWORD dwNum = WideCharToMultiByte(CP_ACP,NULL,strText,-1,NULL,0,NULL,FALSE);
char *psText;
psText = new char[dwNum];
WideCharToMultiByte (CP_ACP, NULL, strText,-1, psText,dwNum,NULL,FALSE);
delete []psText;



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"illegal multibyte sequence" 是一个常见的错误信息,通常在编码换或解析文本时出现。这个错误表示在解码过程中发现了无法解析的多字节序列。 在引用中,这个错误信息是由于使用gbk编码尝试解码字节0xad导致的。在引用中,同样的错误信息是由于使用gbk编码尝试解码字节0xaf导致的。 对于这个问题,一种可能的解决方法是使用正确的编码格式进行解码。在Python中,可以使用`decode`方法指定正确的编码格式,例如使用`utf-8`或`gbk`编码进行解码。 此外,还可以使用`errors='ignore'`参数来忽略无法解码的字节,以避免抛出异常。但是需要注意,忽略错误可能会导致部分内容丢失或乱码。 所以,当遇到"illegal multibyte sequence"错误时,你可以试着更改编码格式或使用`errors='ignore'`参数来处理这个问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [‘gbk‘ codec can‘t decode byte 0xad in position 2: illegal multibyte sequence 错误的解决方法](https://blog.csdn.net/weixin_44714682/article/details/116374636)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [illegal multibyte sequence 解决方法](https://blog.csdn.net/YmeBtc/article/details/102493380)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值