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

使用 WideCharToMultiByte Unicode 与 UTF-8互转的更多相关文章

  1. Unicode和UTF的关系

    目录结构: contents structure [+] 什么是USC UCS的编码方式 Unicode的来源 为什么需要Unicode Unicode的方式 Unicode和UTF UTF和Unic ...

  2. Unicode、UTF-8 和 ISO8859-1

    Unicode.UTF-8 和 ISO8859-1到底有什么区别 1.本文主要包括以下几个方面:编码基本知识,java,系统软件,url,工具软件等. 在下面的描述中,将以"中文" ...

  3. Delphi7中Unicode,ANSI,UTF编码问题

    注解: ANSI     'American Standard Code for Information Interchange' 美国信息互换标准代码 ANSI的'Ascii'编码 Unicode ...

  4. ascii、unicode、utf、gb等编码详解

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

  5. Unicode 与 UTF 字符标准

    Unicode 国际字符标准(UCS)是一个字符编码系统,它被设计用来支持世界各国不同语言书面文体之间的数据交换.处理以及显示.        Unicode用两个字节表示一个字符.前127个字符与A ...

  6. Unicode、UTF-8 和 ISO8859-1到底有什么区别

    说明:本文转载于新浪博客,旨在方便知识总结.原文地址:http://blog.sina.com.cn/s/blog_673c81990100t1lc.html 本文主要包括以下几个方面:编码基本知识, ...

  7. php unicode编码和字符串互转

    php字符串转Unicode编码, Unicode编码转php字符 百度了很多,都一样, 要么不对, 要不就是只是把字符串的汉字转Unicode 经过多次试验查找, 找到了如下方法, 注意:字符串编码 ...

  8. Unicode编码与中文互转

    /** * unicode编码转换为汉字 * @param unicodeStr 待转化的编码 * @return 返回转化后的汉子 */ public static String UnicodeTo ...

  9. JavaScript中unicode编码与String互转(三种方法)

    1.引言 JS本身就支持unicode转string功能,一共有三种方式和String单个字符转unicode编码. 2.方法 //unicode转String 1. eval("'&quo ...

随机推荐

  1. 翻译 | 卷积码的维特比(Viterbi)译码

    对维特比译码的接触很早就开始了,也想过要写一篇总结性的文章,但无奈心中一直有几个疑团没能得到合理的解答.比如什么时候开始进行回溯译码比较合适?维特比译码的性能相比分组码等其他编码的译码性能究竟好在哪里 ...

  2. 理解线程3 c语言示例线程基本操作

    Table of Contents 1. 基本线程的动作 1.1. 设置线程属性 1.1.1. 设置脱离状态 1.1.2. 设置调度属性 1.2. 取消线程 1.3. 主线程创建多个线程示例 2. 了 ...

  3. android Intent onNewIntent 什么时候调用

    1.activity A 的lanch model 为singleTop 此刻,A在activity 栈顶,那么就会调用A 的onNewIntent 如果A不在栈顶,则不会调用. 2.activity ...

  4. django之python3.4及以上连接mysql的一些问题记录

    首先,祭出大杀器whl https://www.lfd.uci.edu/~gohlke/pythonlibs/#mysqlclient django1.x与django2.x 在项目的写法上有一些区别 ...

  5. PKUWC 2018 彻底滚粗记

    PKUWC 2018 彻底滚粗记 如果你们有看到我又在颓, 请以这篇文章让我回忆起这不堪回首的往事. day -3 据说我们要参加PKUWC? 谢总要求我们练习面试,写个稿子. 不知道为什么,有一种不 ...

  6. Eclipse 视图---Eclipse教程第05课

    关于视图 Eclipse视图允许用户以图表形式更直观的查看项目的元数据. 例如,项目导航视图中显示的文件夹和文件图形表示在另外一个编辑窗口中相关的项目和属性视图. Eclipse 透视图(perspe ...

  7. Android保持屏幕常亮唤醒状态

    第一步:  首先添加权限: <uses-permission android:name="android.permission.WAKE_LOCK"></uses ...

  8. lshw

    https://linux.die.net/man/1/lshw lshw(Hardware Lister)是另外一个可以查看硬件信息的工具,不仅如此,它还可以用来做一些硬件的benchmark. 这 ...

  9. sdram之乒乓操作

    在实时显示时,为了保证画面显示的完整性需要对SDRAM进行乒乓操作. SDRAM 中有 4 个bank ,地址分别为00 01 10 11,后面将用 0 1 2 3来描述 bank 0和1 作为第一个 ...

  10. 课时1:我和python的第一次亲密接触

    目录: 一.Python3的下载与安装 二.从IDIE启动Python 三.尝试点新的东西 四.为什么会这样? 五.课时01课后习题及答案 ============================== ...