正确的认识乱码与编码

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 编码将《内存字节》作用于《磁盘文件或者网络文件》的过程,也是将《磁盘文件/网络文件》反解析成《内存字节》的过程. 这个过程中如果 内存字符串到 “字节数组”的编码 与 网络/磁盘文件的之间转化的编解码方式不一致或者不兼容就 会产生乱码. 在一次网络数据访问的过程中,可能有多次这两个步骤的转化.

编码的本质

编码将《内存字节》作用于《磁盘文件或者网络文件》的过程,也是将《磁盘文件/网络文件》反解析成《内存字节》的过程.
这个过程中如果 内存字符串到 “字节数组”的编码 与 网络/磁盘文件的之间转化的编解码方式不一致或者不兼容就 会产生乱码. 在一次网络数据访问的过程中,可能有多次这两个步骤的转化.

写文件的正常流程:内存字符串->"使用编码转化为"-> 字节数组 ,writer将字节数组写入文件,文件头中的编码方式如果和 字符串转化为字节数组的编码不一致或者不兼容,打开文件/再次使用文件头中的编码方式读取文件的时候就会显示乱码, 这个时候方式处理是: 如果明确知道字符串到字节数组转化使用的编码,那么打开文件或者读取文件主动指定使用的编码就行了

上面讲了乱码的原理性,在判断乱码的时候需要考虑输入源的编码是什么,输出源使用了什么编码 , 下面看几个乱码的例子.

乱码的几个例子及思考解决方案

浏览器输入到后端乱码

现象不再赘述

理论上浏览器发送请求的时候,指定编码 并使用指定的编码编码request param或者body 那么后端只要使用浏览器说的编码来 解码就能得到正确内容.

排查方式为 确认request header中的编码方式 与后端接收到并且解码的编码方式是否一致,可以使用抓包的方式判断。如果request header中没有指定编码方式,那么就看浏览器以及服务端的默认编码方式了, 所以在协议交互的过程中编码方式是最好显示指定

后端返回浏览器乱码

现象不再赘述

理论上后端返回response的时候会在response header中带上编码方式,并使用指定的编码方式编码response body 那么浏览器只要使用response header中的编码来 解码就能得到正确内容.

排查方式为 确认response header中的编码方式,了解不同浏览器的默认编码逻辑. 以及html中的其他元素标签对编码的支持

java 枚举类乱码

public enum OfcDeliveryStatusEnum {
    init(0, "数据库-初始化"),
    create(1, "生成运单"),
    accept(2, "配送待分配")
        private Integer code;
    private String desc;
}

现象:当在代码中想要使用OfcDeliveryStatusEnum.create.getDesc()的时候 发现获取到的是乱码

原因:java源文件是UTF-8格式保存的,maven编译使用的GBK格式编译生产class文件,这中间有一个文件读取到内存再输出到文件的过程,编码的差异导致格式被破坏从而产生乱码.

排查方式需要明白java的工作原理,OfcDeliveryStatusEnum.create.getDesc() 程序运行起来后直接从内存的metaspace中取出来的,如果内存中通过utf-8查看是乱码,那么内存中已经乱码了,而内存值是通过加载class文件生成的,那么class文件难道也是乱码吗?class文件是maven从java源文件编译而来,源文件正常,那只可能是编译过程出了问题

数据库存储乱码

现象不再赘述

应用程序连接mysql server之间有一次通信会话写入数据,mysql server到 存储到磁盘有一次文件存储,从mysqlserver 查询数据返回到前端有一次通信会话 可以看到这中间有3次通信,那就存在三次编码转化,分别抓住两次编码转化是否一致。

1)character_set_server:mysql server默认字符集。
2)character_set_database:数据库默认字符集。
3)character_set_client:MySQL server假定客户端发送的查询使用的字符集。
4)character_set_connection:MySQL Server接收客户端发布的查询请求后,将其转换为character_set_connection变量指定的字符集。
5)character_set_results:mysql server把结果集和错误信息转换为character_set_results指定的字符集,并发送给客户端。
6)character_set_system:系统元数据(字段名等)字符集

Linux系统显示乱码

https://help.aliyun.com/document_detail/169436.html

总结


不管什么场景,只要存在一次读写操作,如果使用的编码不一致就可能导致乱码, 现实中碰到的场景都可能使用多次读写操作的复合场景,判断乱码的方式需要分段判断,最终确认第一次出现编码不一致的一段

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
Oracle 关系型数据库 Java
解决读取Oracle数据库US7ASCII编码乱码问题
今天和第三方对接数据时,对方提供了一个视图US7ASCII编码,给代码调试带来了很大的不便。程序输出的mybatis获取的对象及new String(s.getBytes("ISO8859-1"), "GB2312")加解密后都是乱码。
1739 1
|
6月前
|
计算机视觉
中文字符串时出现乱码
【6月更文挑战第3天】
183 4
|
存储 Java 关系型数据库
【精炼易懂】字符集、编码、乱码问题、ASCII、GBK、Unicode、UTF-8详解+实例说明
【精炼易懂】字符集、编码、乱码问题、ASCII、GBK、Unicode、UTF-8详解+实例说明
6007 4
|
存储 Windows
“浅入深处“编码历史,字符串编码(ASCII, GBK, ANSI, Unicode, UTF-8编码),为什么记事本默认ANSI编码,Unicode和UTF8有什么区别
“浅入深处“编码历史,字符串编码(ASCII, GBK, ANSI, Unicode, UTF-8编码),为什么记事本默认ANSI编码,Unicode和UTF8有什么区别
144 0
|
存储 算法 Java
【字符编码】字符编码 && Base64编码算法
  在前面的解决乱码的一文中,只找到了解决办法,但是没有为什么,说白了,就是对编码还是不是太熟悉,编码问题是一个很简单的问题,计算机从业人员应该也必须弄清楚,基于编码的应用有Base64加密算法,然后,这个问题一直放着,想找个机会解决。于是乎,终于逮到机会,开始下手。
243 0
【字符编码】字符编码 && Base64编码算法
|
机器学习/深度学习 算法 索引
关于Onehot编码的总结
关于Onehot编码的总结
613 0
关于Onehot编码的总结
|
存储 安全 关系型数据库
为什么编码不同会出现乱码?
本章节通过情景模拟,和大家一起探讨为什么编码不同会出现乱码
|
数据格式 XML .NET
|
Java
编码问题
字节流(二进制流) 首先明确“字节(Byte)”和“字符(Character)”的大小: 1 byte = 8 bit 1 char = 2 byte = 16 bit (Java默认UTF-16编码) 字节流是由字节组成的,字符流是由字符组成的.
748 0