为什么编码不同会出现乱码?
实为吾之愚见,望诸君酌之!闻过则喜,与君共勉
第一章 情景模拟
第一节 工具准备
准备一些需要的工具,方便后面的虚拟场景
1.1.1 模拟密码本A
密码本A的字符坐标规则:假设一个字符的密文由三部分组成,顺序分别是"U+5600的56"+"表格最上方的坐标"+"表格最左边的坐标",举例"570B"是"國","56E7"是"囧",如下第一个和第二个密码表,这些密文是16进制的格式,下同
1.1.2 模拟密码本B
密码本B的字符坐标规则:假设一个字符的密文由三部分组成,顺序分别是"表格左上角的字符串"+"表格最左边的坐标"+"表格最上方的坐标",举例"87E5"是"囧","87F8"是"國",如下第一个密码表,这些密文也是16进制的格式,下同
1.1.3 密文的加密规则
即我们可能还需要对我们拿到的密文进行再一次的加密,比如”囧”的密文是” "56E7”按照开头假设的密文规则,这是16进制的数,那我们还需要把这个16进制的56E7通过一定的规则,再次加密,针对这两个密码本的加密规则假设如下:
密码本A密文再次加密规则:
16进制密文转换为10进制后对应的范围 |
16进制数转换为2进制后对应的加密格式 |
0至127 |
0xxxxxxx |
128至2047 |
110xxxxx 10xxxxxx |
2048至65535 |
1110xxxx 10xxxxxx 10xxxxxx |
65536至2097151 |
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
比如56E7这个密文再次加密,他转换成10进制是22247,22247在”2048-65535”的范围内,那他的加密格式就是1110xxxx10xxxxxx10xxxxxx,暂且称它为466格式,如何加密呢?如下:
- 先把56E7转换成二进制为:0101011011100111
- 按照1110xxxx 10xxxxxx 10xxxxxx的格式,对56E7转换成的二进制0101011011100111进行拆分:
首先,0101011011100111--------按照4 6 6的格式拆分后--------->0101 011011 100111
然后,对0101 011011 100111按照466格式进行转换------->11100101 10011011 10100111
把转换后的111001011001101110100111转换为16进制就是e59ba7,e59ba7就是56E7再次加密的最终密文,这样就由原来的"56E7"是"囧"变成" E59BA7"是"囧",甚至可以根据这个加密方式,生成一个新的密码本C
密码本B的再次加密规则:
密码本B的16进制密文不再进行二次加密,直接使用获得的16进制密文,例如56E7不会与密码本A一样再次加密,直接使用56E7
第二节 漫画情景
1.2.1 情景故事
模拟一个虚构的场景,场景里的元素是:
- 远在外地的小明
- 与小明同部门的小丽
- 安全部门的同学
- 与小明同部门的小红
- 一个信息安全非常严格的公司
- 加密的档案管理
今天,小明需要将一个很重要的数据,告诉公司的小丽把这个数据存到小明自己的档案里:
、
小明发现,他获取到的数据是“闃块噷”,而不是3天前存储的”阿里”,如果小明意识到自己的错误,把小红寄给他的数据先转换成密码本B的密文,再用转换的密文对照密码本A查找呢?
第二章 Mysql的乱码
如果上面的场景,放到数据库里,会一样吗?拿mysql作为例子,测试一下,数据从客户端发送到server并存入表中成为数据然后查询该数据的过程,mysql中控制这个过程的编码的参数主要是character_set_client,character_set_connection,character_set_results,表字符集以及程序字符集等,可以看下文档。
第一节 mysql的情景对应
字符集:
unicode gbk
字符编码规则:
utf8:只针对unicode,相当于第一章情景中的二次加密
gbk:不对gbk再编码
参数与情景对应:
程序字符集:小明加密数据时使用的密码本A
character_set_client:小明在寄信时,写错了数据加密方式,写的是密码本B,而不是A
character_set_connection:安全规则,需要转换的加密格式
character_set_results:寄信时需要使用的加密格式
表或者库字符集:小明的档案的加密格式
Server端处理:小丽/小红
第二节 mysql测试
2.2.1 第一次测试
参数设置:
程序字符集:utf8
character_set_client:utf8
character_set_connection:utf8
character_set_results:utf8
表或者库字符集:utf8
Server端处理:mysql program
测试结果:无乱码
2.2.2 第二次测试
参数设置:
程序字符集:utf8
character_set_client:gbk
character_set_connection:utf8
character_set_results:utf8
表或者库字符集:utf8
Server端处理:mysql program
测试结果:只设置set character_set_client=gbk后,查询乱码
2.2.3 乱码猜猜猜
结合第一章的场景,为什么乱码呢?
2.2.3.1 第一步处理
程序将"阿里"以utf8编码进行转换发送(unicode转utf8与情景中的规则一致),但是不小心在session中设置了character_set_client=gbk,character_set_connection =utf8,character_set_results=utf8,类似如下现象:
形状:阿里
Utf8方式下的16进制编码值:E998BF E9878C
二进制:11101001 10011000 10111111 11101001 10000111 10001100(utf8将2个汉字转换后6个字节)
2.2.3.2 第二步处理
到达server端,server通过character_set_client=gbk知道客户端发过来的数据是gbk编码的(实际是utf8编码的,客户端不小心写错了),那server端就按照gbk来解码了,解码后如下:
二进制:11101001 10011000 10111111 11101001 10000111 10001100(程序端的两个汉字经过utf8转换后的二进制数据,一共6字节,但是server端不知道,因为server通过character_set_client=gbk得知,这不是utf8,这是gbk的,我要按照gbk来解码)
gbk转换后的16进制编码值:E998 BFE9 878C(通过这个编码,查找gbk的码表,获取他的形状为:闃块噷)
2.2.3.3 第三步处理
Servre还需要检查character_set_connection参数,发现character_set_connection=utf8,而之前是gbk,那就需要将gbk的这三个字节转换为utf8,怎么转换呢?按照第一章的情景,先转unicode(密码本A),再将得到的unicode再次编码为utf8:
“闃块噷“三个字符的unicode编码是 95c3 5757 5677
转换成二进制:10010101 11000011 01010111 01010111 01010110 01110111(这三个汉字是6个字节)
通过unicode,再转换为utf8的实现方式,实现方式如下:
首先转换95c3( 1001010111000011),他的范围在第三行(3字节)
1001 010111 000011,根据第三行的格式,从低位往高位的顺序,按照格式分成4 6 6 的格式
按照格式填充,填充后:11101001 10010111 10000011,填充后转换成16进制是e99783,则”闃”在utf8中就是”e99783”,同样,”块”在utf8中就是” e59d97”,” 噷”在utf8中就是” e599b7”, 于是转换后的结果就是:
编码:E99783 E59D97 E599B7
二进制:111010011001011110000011111001011001110110010111111010000000000000000000
2.2.3.4 第四步处理
server端处理好之后,继续向下走,准备存储数据了,检查了存储的表是utf8的,不需要转换了,直接存储
编码:E99783 E59D97 E599B7
二进制:111010011001011110000011111001011001110110010111111010000000000000000000
2.2.3.5 查询返回
程序插入完成后,想查询下之前插入的数据,于是客户端在当前session下执行了select操作,server端收到请求后,去表里找数据,找到了之前写入的数据
111010011001011110000011111001011001110110010111111010000000000000000000
server检查character_set_results=utf8,与表的字符编码是一致的,那就不需要转换了,直接把111010011001011110000011111001011001110110010111111010000000000000000000给程序了,程序收到后,就解码111010011001011110000011111001011001110110010111111010000000000000000000,因为程序本身也是utf8的,不需要转换,于是按照utf8来解码数据,111010011001011110000011111001011001110110010111111010000000000000000000的16进制是E99783E59D97E599B7(符号是闃块噷,乱码了)
为什么编码不同会出现乱码?相关推荐
- 解决Excel打开UTF-8编码的CSV文件乱码的问题 实测好用
解决Excel打开UTF-8编码的CSV文件乱码的问题 1 2 3 4 5 6 分步阅读 CSV是一个平面文件,它的编码方式有多种.比如,MongoDB以UTF-8格式存储数据,在使用mongoexp ...
- HTML编码问题导致的乱码
今天一个学弟问了一个问题,它写的HTML代码打开显示的是乱码. 然后就给我发来了代码. 就一个HTML文件和一个文件夹,打开一看,很简单的代码. <!DOCTYPE html> <h ...
- Java中为什么有时候通过指定编码集无法解决乱码
@TOC Java中为什么有时候通过指定编码集无法解决乱码 当我们编程的时候都遇到过出现乱码的情况,这通常是使用了不匹配的编码表导致的,这是我们可以用指定的编码表的方式解决乱码问题如下面 的代码 St ...
- 为什么文本乱码呢,我来告诉你什么是编码,解码,乱码
为什么文本乱码呢,我来告诉你什么是编码,解码,乱码 1.编码 二进制 十六进制 字符集 ASCII编码 ISO-8859-1编码 windows-1252编码 GB2312编码 GBK编码 GB180 ...
- 前端网页、php与mysql数据库字符编码(解决中文等乱码问题
web开发中经常涉及前端网页--php--mysql之间的数据交互,当数据只有英文时通常不会有什么问题,但一旦涉及中文,三个地方的某一处字符编码不一致(如,网页使用的时gbk而mysql使用utf-8 ...
- wamp php字符编码,关于Apache默认编码错误 导致网站乱码的解决方案
最近经常有同学在使用LAMP/WAMP时,遇到这样的编码错误问题: A网站程序编码UTF-8编码安装成功,运行成功. B网站程序编gb2312也要安装在同一服务器上. 这样就出现问题了,Apache默 ...
- Chrome 技巧篇-浏览器网页设置编码,解决网页乱码问题,最新版charset插件获取,UTF-8编码设置
非常简单,安装一个Charset插件就好了. 获取方式: 小蓝枣的资源仓库,提取码:ih2n 有乱码的话,一般设置为UTF-8编码就好了. 喜欢的点个赞❤吧!
- mysql navicat编码保持一致不乱码
https://edu.csdn.net/course/play/7912 mysql在安装的时候要指定utf-8,但是如果同时用navicat,则会出现二者编码不能同步的问题,要么mysql中文,n ...
- mysql中的编码问题_mysql存储乱码之编码问题
在编写项目中,出现乱码问题有比较多的地方,当前笔记为在项目中没有乱码,在存储mysql 中出现乱码. 1.通过下面语句查看数据库.表的客户端.服务端编码是否一致,是否能存储中文. show varia ...
最新文章
- 大话数据结构书籍及配套源码
- 清华《人工智能之认知图谱》:中美高水平学者数量领跑全球
- EK算法应用,构图(POJ1149)
- Centos下本地连接postgresql时出现认证错误的问题
- mysql 视图慢_第03问:磁盘 IO 报警,MySQL 读写哪个文件慢了?
- 【微信小程序】跳转到另一个微信小程序
- 标记偏见_分析师的偏见
- java 最快平衡几个值_Java 集合框架面试问题集锦
- 任正非:华为不会拆分;以色列公司称可解锁所有 iOS 设备;Java 13 要来了! | 极客头条...
- Linux 性能测试与分析-转
- TrueCrypt加密安全问题
- 云原生这么火,你再不了解就out了
- 怡红快绿 [转自TK's Blog]
- java 反射 protected_通过Java反射机制访问private,protected变量和方法
- 如何管理应用的生命周期?
- 第2-1课:非线性方程与牛顿迭代法
- 三年级计算机绘画第二课堂教案,美术第二课堂计划讲解.docx
- conda search cuda后没有版本10的问题
- 关于关联表用code还是id的见解
- java的 I/O 输入输出流详解
热门文章
- UVALive 4216 	 Pole Position
- OpenGL中关于坐标系原点在左上角还是左下角的一些整理
- 汇编语言中的乘除法用到的寄存器问题(较详细解析)(用到AX和DX,乘数和除数用其他寄存器和存储器)
- Matlab Robotic Toolbox V9.10工具箱(二):正/逆运动学
- 算法分析之-主方法分析递归式
- js如何判断字符串里面是否含有某个字符串
- Broadcom BCM4322(如:HP 6530b)wifi不能用解决办法
- 单独写原则Single Writer Principle
- 一个简单的Spring的AOP例子(JAVA面向切面编程)
- mysql 查询slow log状态,MySQL开启慢查询日志log-slow-queries的方法