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 类型变量来分别接收UnicodeUTF-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)的更多相关文章

  1. Linux 平台和 Windows平台下 Unicode与UTF-8互转

    Windows: unsigned char * make_utf8_string(const wchar_t *unicode) { , index = , out_index = ; unsign ...

  2. 使用 WideCharToMultiByte Unicode 与 UTF-8互转

    1.简述 最近在发送网络请求时遇到了中文字符乱码的问题,在代码中调试字符正常,用抓包工具抓的包中文字符显示正常,就是发送到服务器就显示乱码了,那就要将客户端和服务器设置统一的编码(UTF-8),而我们 ...

  3. [C/C++]_[Unicode转Utf8,Ansi转Unicode,Ansi文件转Utf8文件]

    http://blog.csdn.net/infoworld/article/details/15337665 场景: 1.也就只有windows需要那么麻烦,还搞一个ANSI编码.学学mac os ...

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

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

  5. Unicode 和 UTF-8 有何区别?

    Unicode符号范围 (一个字符两个字节)     | UTF-8编码方式 (十六进制)     | (二进制) —————————————————————– 这儿有四个字节从-----00 00 ...

  6. Unicode和UTF-8的关系

    Unicode和UTF-8都是表示编码,这个我一直都知道,但是这两个实际上是干什么用的,到底是怎么编码的,为什么有了Unicode还要UTF-8,它们之间有什么联系又有什么区别呢?这个问题一直困扰着我 ...

  7. 字符编码笔记:ASCII,Unicode和UTF-8

    很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物.他们看到8个开关状态是好的,于是他们把这称为"字节". 再后来,他们又做了一些可以处理 ...

  8. 字符编码笔记:ASCII,Unicode和UTF-8 转

    本文出处 http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html 只是为了记录一下省得要去搜. 今天中午,我突然想搞清楚 ...

  9. [转]字符编码笔记:ASCII,Unicode和UTF-8

    转自:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html 作者: 阮一峰 日期: 2007年10月28日 今天中午, ...

随机推荐

  1. 位运算 ZOJ 3870 Team Formation

    题目传送门 /* 题意:找出符合 A^B > max (A, B) 的组数: 位运算:异或的性质,1^1=0, 1^0=1, 0^1=1, 0^0=0:与的性质:1^1=1, 1^0=0, 0^ ...

  2. MD5加密(16/32)

    public string MD5(string str, int code) { if (code == 16) //16位MD5加密(取32位加密的9~25字符) { return System. ...

  3. HDU 2896 (AC自动机模板题)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2896 题目大意:多个模式串.多个匹配串.其中串的字符范围是(0~127).问匹配串中含有哪几个模式串 ...

  4. 【wikioi】1229 数字游戏(dfs+水题)

    http://wikioi.com/problem/1229/ 赤裸裸的水题啊. 一开始我认为不用用完全部的牌,以为爆搜会tle.. 可是我想多了. 将所有状态全部求出,排序后暴力判断即可. (水题有 ...

  5. tyvj100题留念

    全是水题萌萌哒~0~... 留个纪念

  6. CSS透明度大汇总

    近年来,CSS不透明算得上是一种相当流行的技术,但在跨浏览器支持上,对于开发者来说,可以说是一件令人头疼的事情.目前还没有一个通用方法,以确保透明度设置可以在目前使用的所有浏览器上有效. 这篇汇总主要 ...

  7. iOS移动开发周报-第25期

    iOS移动开发周报-第25期 [摘要]:本期iOS移动开发周报带来如下内容:苹果发布 iPhone6 和 Apple Watch.Swift 1.0 GM发布.Xcode 6支持PDF Vector作 ...

  8. vb.net-三种将datagridview数据导出为excel文件的函数

    第一种方法较慢,但是数据格式都比较好,需要引用excel的 Microsoft.Office.Interop.Excel.dll  office.dll #Region "导出excel函数 ...

  9. [转]C#基础回顾:Asp.net 缓存

    本文转自http://www.cnblogs.com/stg609/archive/2009/03/22/1418992.html 缓存的作用      你买电脑的时候,是否会在意CPU的二级缓存?是 ...

  10. [转]把动态页面.aspx 生成静态页面.html

    本文转自:http://blog.csdn.net/csb5201314/article/details/5391688 如果要把主页Index.aspx 生成静态页面 Index.html后输出会提 ...