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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

结果如下:

我们看到转为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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

从结果中我们看到,成功地将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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

实例二:

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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

这里在中文 “中国”和“你好”之间加了英文的标点符号,显示正常。

实例三:

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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

这里在中文 “中国”和“你好”之间加了中文的标点符号,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个字节表示一个符号,根据不同的符号而变化字节长度。

网上也有好多关于字符问题的资料,但是说法不一,所以还是要经过多方验证,这里需要注意一下。

MFC开发IM-第二十二篇、C++中 Unicode 与 UTF-8 编码互转相关推荐

  1. js 浅拷贝直接赋值_第二十二篇 JS中浅拷贝的方法有哪些?

    重要:什么是拷贝?之前也写过类似的文章,大家可以看<理解js的深拷贝和浅拷贝原理和实现的方法> 首先来直观的感受一下什么是拷贝. let arr = [1, 2, 3]; let newA ...

  2. 【C++笔记】第二十二篇 STL

    C++的STL 1. STL 1.1 STL诞生 ① 长久以来,软件界一直希望建立一种可重复利用的东西. ② C++的面向对象和泛型编程思想,目的就是复用性的提升. ③ 大多数情况下,数据结构和算法都 ...

  3. Python开发【第十二篇】:DOM

    文档对象模型(Document Object Model,DOM)是一种用于HTML和XML文档的编程接口.它给文档提供了一种结构化的表示方法,可以改变文档的内容和呈现方式.我们最为关心的是,DOM把 ...

  4. Android UI开发第三十二篇——Creating a Navigation Drawer

    Navigation Drawer是从屏幕的左侧滑出,显示应用导航的视图.官方是这样定义的: The navigation drawer is a panel that displays the ap ...

  5. 第二十二篇玩转【斗鱼直播APP】系列之弹出房间界面

    弹出房间界面 功能说明 区分弹出秀场&普通房间 如果用户是秀场直播,那么弹出秀场房间界面 如果用户是电脑直播,那么弹出普通房间界面 秀场界面弹出 直接以Model方式,从底部弹出即可 普通界面 ...

  6. 【手写 Vue2.x 源码】第二十二篇 - dep 和 watcher 关联

    一,前言 上篇,主要介绍了 Vue 依赖收集的过程分析: 介绍了 Vue 的响应式特性 介绍了 Vue 的依赖收集过程 介绍了 dep 和 watcher 以及观察者模式: 本篇,Vue 依赖收集的实 ...

  7. Java第二十二篇:详述嵌套for循环执行顺序,小白看了也能懂

    嵌套for循环执行步骤: 1.先判断最外层循环条件,若满足条件则进入第一层循环体;2.进入第一层循环体后进行第二层循环条件判断,若满足判断条件,进入第二层循环体;3.由内而外执行循环体操作:4.执行完 ...

  8. SpringBoot第二十二篇: 创建含有多module的springboot工程

    这篇文章主要介绍如何在springboot中如何创建含有多个module的工程,栗子中含有两个 module,一个作为libarary. 工程,另外一个是主工程,调用libary .其中libary ...

  9. 第二十二篇 玩转数据结构——构建动态数组

    1.. 数组基础 数组就是把数据码成一排进行存放. Java中,数组的每个元素类型必须相同,可以都为int类型,string类型,甚至是自定义类型. 数组的命名要语义化,例如,如果数组用来存放学生的成 ...

  10. Avalonia跨平台入门第二十二篇之人脸检测

    在前面分享的几篇中咱已经玩耍了Popup.ListBox多选.Grid动态分.RadioButton模板.控件的拖放效果.控件的置顶和置底.控件的锁定.自定义Window样式.动画效果.Expande ...

最新文章

  1. 【matlab】第二次上机课
  2. 卡耐基梅隆大学专家谈核心技术市场化:「AI 周边相关机遇最大」
  3. SpringBoot 集成 WebSocket,实现后台向前端推送信息
  4. webconfig的connectionStrings字段
  5. 前端JavaScript基础知识点
  6. 交换机组最常见的8大故障及解决方法
  7. 光纤连接器百科小知识
  8. 从零开始学视觉Transformer (7):Swin Transformer-2
  9. Java命令:jinfo — 查看进程参数
  10. Linux关闭防火墙详述
  11. python用schedule模块实现定时任务
  12. Tomcat几种启动报错及解决办法
  13. YARN的服务库和事件库
  14. matlab2c使用c++实现matlab函数系列教程-save函数
  15. 基础资料表:行政区划、车型库、行业类别 可下载
  16. 3D点云人脸鼻尖检测算法
  17. 悲剧的山寨采用的新芯片资料汇总(更新Rk3066)
  18. 圣诞帽php,微信小程序“圣诞帽”的实现方法
  19. 技师学院计算机老师,技师学院计算机工程系组织开展观摩课活动
  20. 大学英语综合教程三 Unit 7 课文内容英译中 中英翻译

热门文章

  1. Linux添加环境变量与GCC编译器添加INCLUDE与LIB环境变量
  2. BZOJ5073 小A的咒语(动态规划)
  3. informix(南大通用)sql语法的差异
  4. 【转载】小米2进入recovery的方法
  5. 大型网站技术架构(三)--架构核心要素(转)
  6. World Wind Java开发之二 使用Winbuilders设计图形用户界面(转)
  7. arcgis 10.1 导入数据到oracle 发布地图服务
  8. PyTorch 1.0 中文文档:torch.hub
  9. Web Hacking 101 中文版 十五、代码执行
  10. python实现的摩斯电码解码\编码器