Unicode与UTF8相互转化(使用MultiByteToWideChar)
1、简述
最近在发送网络请求时遇到了中文字符乱码的问题,在代码中调试字符正常,用抓包工具抓的包中文字符显示正常,就是发送到服务器就显示乱码了,那就要将客户端和服务器设置统一的编码(UTF-8),而我们程序中 一般用的是Unicode编码,所以这就需要将中文字符转为UTF-8格式的,其他英文字符和数字就不需要转了。下面就讲述一下方法。
2、代码之路
Unicode 转 UTF-8
char* UnicodeToUtf8(const wchar_t* unicode)
{
int len;
len = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, NULL, 0, NULL, NULL);
char *szUtf8 = (char*)malloc(len + 1);
memset(szUtf8, 0, len + 1);
WideCharToMultiByte(CP_UTF8, 0, unicode, -1, szUtf8, len, NULL, NULL);
return szUtf8;
}
int main(int argc, char *argv[])
{
wchar_t* wCharUnicode = L"中国";
char* cCharUtf = UnicodeToUtf8(wCharUnicode);
return 0;
}
结果如下:
我们看到转为UTF-8之后在VS中查看时显示为其他字符。为了验证我们转的字符是否正确,我们可以借用NotePad++这个工具。我们新建一个文件,用NotePad++打开,文件编码默认为ANSI格式,这里显示的跟VS中调试时显示的值是一样的。
我们修改文件编码为UTF-8之后再看一下,是不是显示正常了,所以验证了转换代码正确。
UTF-8 转 Unicode
CString UTF82WCS(const char* szU8)
{
//预转换,得到所需空间的大小;
int wcsLen = ::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), NULL, 0);
//分配空间要给'\0'留个空间,MultiByteToWideChar不会给'\0'空间
wchar_t* wszString = new wchar_t[wcsLen + 1];
//转换
::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), wszString, wcsLen);
//最后加上'\0'
wszString[wcsLen] = '\0';
CString unicodeString(wszString);
delete[] wszString;
wszString = NULL;
return unicodeString;
}
int main(int argc, char *argv[])
{
wchar_t* wCharUnicode = L"中国";
char* cCharUtf = UnicodeToUtf8(wCharUnicode);
CString strUnicode = UTF82WCS(cCharUtf);
return 0;
}
从结果中我们看到,成功地将UTF-8编码转为Unicode编码,代码很简单,还是要多思考,多练,多查阅资料。
给出几个小实例,看一下转换结果。
下面为测试代码:
实例一:
int length;
wchar_t* wCharUnicode = L"中国你好";
length = wcslen(wCharUnicode); // length = 4;
char* cCharUtf = UnicodeToUtf8(wCharUnicode);
length = strlen(cCharUtf); // length = 12;
// 将UTF格式的char*转为CString
CString strUtf(cCharUtf);
length = strUtf.GetLength(); // length = 6;
CString strUnicode = UTF82WCS(cCharUtf);
length = strUnicode.GetLength(); // length = 4;
实例二:
int length;
wchar_t* wCharUnicode = L"中国,你好abc";
length = wcslen(wCharUnicode); // length = 8;
char* cCharUtf = UnicodeToUtf8(wCharUnicode);
length = strlen(cCharUtf); // length = 16;
// 将UTF格式的char*转为CString
CString strUtf(cCharUtf);
length = strUtf.GetLength(); // length = 10;
CString strUnicode = UTF82WCS(cCharUtf);
length = strUnicode.GetLength(); // length = 8;
这里在中文 “中国”和“你好”之间加了英文的标点符号,显示正常。
实例三:
int length;
wchar_t* wCharUnicode = L"中国,你好abc";
length = wcslen(wCharUnicode); // length = 8;
char* cCharUtf = UnicodeToUtf8(wCharUnicode);
length = strlen(cCharUtf); // length = 18;
// 将UTF格式的char*转为CString
CString strUtf(cCharUtf);
length = strUtf.GetLength(); // length = 10;
CString strUnicode = UTF82WCS(cCharUtf);
length = strUnicode.GetLength(); // length = 8;
这里在中文 “中国”和“你好”之间加了中文的标点符号,cCharUtf 在VS中看不到值,但是可以转成CString查看其值,结果正确。
尾
我们从三个不同实例的测试结果中看到一个中文字符或者中文标点符号,占了三个字节(有资料显示 UTF-8编码:采用变长字节 ,1 :ASCII, 2: 希腊字母, 3: 汉字, 4: 中日韩超大字符集,这里常用汉字占用3个,不常用的汉字占用4个字节 ),中文标点符号与英文标点符号差了两个字节,这里要特别注意,而英文字符在UTF-8下都为一个字节。
同时我们可以看到用CString 类型变量来分别接收Unicode和UTF-8编码的字符,这里我们看到长度不一致(这里特值字符长度,并不是字符所占字节数),虽然我们看到UTF-8编码比Unicode编码要长,但是并不是绝对的,因为UTF-8在存储不同字符时所占的内存大小不一样,就比如存储ASCII码 就只需要一个字节,而Unicode需要两个字节,关于编码问题还是挺复杂的,而正是Unicode储存ASCII也需要两个字节,这里就出现了UTF-8、UTF-16、UTF-32等不同的字符编码格式,至于为什么会出现这么多的编码格式,那也是因为每种编码格式保存字符的空间大小不一致,就比如UTF-8保存一个英文字母只需要一个字节,而Unicode需要两个字节,但是保存一个中文字符,UTF-8需要三个字节,而Unicode则需要两个字节。
UTF全称为unicode transformation format,其实说白了,UTF-8就是Unicode的实现方式之一, ,UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。
网上也有好多关于字符问题的资料,但是说法不一,所以还是要经过多方验证,这里需要注意一下。
http://blog.csdn.net/goforwardtostep/article/details/53207804
Unicode与UTF8相互转化(使用MultiByteToWideChar)的更多相关文章
- Linux 平台和 Windows平台下 Unicode与UTF-8互转
Windows: unsigned char * make_utf8_string(const wchar_t *unicode) { , index = , out_index = ; unsign ...
- 使用 WideCharToMultiByte Unicode 与 UTF-8互转
1.简述 最近在发送网络请求时遇到了中文字符乱码的问题,在代码中调试字符正常,用抓包工具抓的包中文字符显示正常,就是发送到服务器就显示乱码了,那就要将客户端和服务器设置统一的编码(UTF-8),而我们 ...
- [C/C++]_[Unicode转Utf8,Ansi转Unicode,Ansi文件转Utf8文件]
http://blog.csdn.net/infoworld/article/details/15337665 场景: 1.也就只有windows需要那么麻烦,还搞一个ANSI编码.学学mac os ...
- Ansi、Unicode、UTF8字符串之间的转换和写入文本文件
转载请注明出处http://www.cppblog.com/greatws/archive/2008/08/31/60546.html 最近有人问我关于这个的问题,就此写一篇blog Ansi字符串我 ...
- Unicode 和 UTF-8 有何区别?
Unicode符号范围 (一个字符两个字节) | UTF-8编码方式 (十六进制) | (二进制) —————————————————————– 这儿有四个字节从-----00 00 ...
- Unicode和UTF-8的关系
Unicode和UTF-8都是表示编码,这个我一直都知道,但是这两个实际上是干什么用的,到底是怎么编码的,为什么有了Unicode还要UTF-8,它们之间有什么联系又有什么区别呢?这个问题一直困扰着我 ...
- 字符编码笔记:ASCII,Unicode和UTF-8
很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物.他们看到8个开关状态是好的,于是他们把这称为"字节". 再后来,他们又做了一些可以处理 ...
- 字符编码笔记:ASCII,Unicode和UTF-8 转
本文出处 http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html 只是为了记录一下省得要去搜. 今天中午,我突然想搞清楚 ...
- [转]字符编码笔记:ASCII,Unicode和UTF-8
转自:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html 作者: 阮一峰 日期: 2007年10月28日 今天中午, ...
随机推荐
- 数学 赛码 1010 GCD
题目传送门 /* 数学:官方题解 首先,数组中每个元素至少是1 然后对于任意一个询问Li, Ri, Ansi, 说明Li ~ Ri中的元素必定是Ansi的倍数,那么只需将其与Ansi取最小公倍数即可 ...
- windows 服务安装脚本拾遗
转自:http://blog.csdn.net/susubuhui/article/details/7881096 1.安装脚本 echo 请按任意键开始安装客户管理平台的后台服务 echo. pau ...
- BZOJ3322 : [Scoi2013]摩托车交易
求出最大生成树,则两点间的最大容量为树上两点间的边权的最小值. 设$lim[i]$表示第$i$个订单的城市允许携带的黄金上限,则 $lim[i]=\min(lim[i+1],a[i]和a[i+1]点间 ...
- 理解cookie的path和domain属性
今天在做验证码时发现一个问题:A.B窗口都打开同一个页面,A先生成一个验证码,B再生成验证码,这时A所生成的验证码被B覆盖掉了.原因是使用了同名的cookie来存储验证码.一时找不到解决方法就参考了W ...
- 一致性 hash 算法
consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在 cache 系统中应用越来越广泛: 1 ...
- mongodb与mysql命令对比
mongodb与mysql命令对比 传统的关系数据库一般由数据库(database).表(table).记录(record)三个层次概念组成,MongoDB是由数据库(database).集合(col ...
- jstl fn标签
JSTL使用表达式来简化页面的代码,这对一些标准的方法,例如bean的getter/setter方法,请 求参数或者context以及session中的数据的访问非常方便,但是我们在实际应用中经常需要 ...
- SSH框架优缺点
SSH框架优缺点 开源是3个框架共有的优点 Struts2框架(MVC框架)的优点如下: 1) 实现了MVC模式,层次结构清晰,使程序员只需关注业务逻辑的实现: 2) 丰富的标签库,大大提高了开发 ...
- Intent学习笔记
Intent首先字面意思大概是意图.负责activity之间或者,activity与service等(我只知道这么点)之间信息的传递.就跟快递员起的作用差不多(我这这么理解),由一下六部分组成: Co ...
- 连接sql server的语句
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...