通俗易懂地解决中文乱码问题(1) --- 跨平台乱码

简介: 原文:【原创】通俗易懂地解决中文乱码问题(1) --- 跨平台乱码本来是只打算写一篇关于中文乱码的blog的,但是发现要讲的东西跨度有点大,不好写到同一篇里面,所以分开了。 另一篇是  《【原创】通俗易懂地解决中文乱码问题(2) --- 分析解决Mysql插入移动端表情符报错 ‘incorrect string value: '\xF0...》 。
原文: 【原创】通俗易懂地解决中文乱码问题(1) --- 跨平台乱码

本来是只打算写一篇关于中文乱码的blog的,但是发现要讲的东西跨度有点大,不好写到同一篇里面,所以分开了。

另一篇是  【原创】通俗易懂地解决中文乱码问题(2) --- 分析解决Mysql插入移动端表情符报错 ‘incorrect string value: '\xF0...

这一篇重点在编码的理论,另一篇重点在解决问题及思路。

 

一、问题的开始

中文乱码问题经常出现在实际工程中,尤其容易发生在经验不足的团队对问题预估不足的情况下。网站开发,社交聊天等对输入信息不可控的应用往往是重灾区。再加上移动互联网的火热,新兴字符和表情也开始频繁被使用,如果不能达到足够的支持,对用户体验来说是个灾难。所以,在设计系统的开始,要严格把控字符编码。以大体明确怎么做是不会出错的(严格按规则限制往往难以把控,并且容易漏掉被钻空子,所以做到不出错是出发点)。

 

二、Unicode

Unicode是本文的重点。

Unicode是一种通用字符集,是对字符的定义。和之对应的也有,比如 ISO 8859-1。但Unicode被广泛使用并成为业界的标准,所以我们可以认为Unicode就是对计算机里字符的定义,在内存中的表现是0,1串。

而且,Unicode的编码很干净,它为 字符而非字形定义唯一的代码。换句话说,统一码以一种抽象的方式(即数字)来处理字符,并将视觉上的演绎工作(例如字体大小、外观形状、字体形态、文体等)留给其他软件来处理,例如网页浏览器或是文字处理器。举个例子,如 “ɑ/a”、“強/强”、“戶/户/戸”。(引自wiki)

这样,Unicode本身要做的任务很明确,就是合适的扩充编码。

 

三、UTF-8

UTF-8是Unicode的一种实现方式,是可变长的字符编码。与之对应的还有GBK(固定长度),Latin,UTF-16(Unicode的完全式)等等。

这些为什么是实现方式呢?不是Unicode已经定义好了吗?其实这也是计算机学科经常用的方法,这些不同的编码就类似于针对Unicode的各种trick。

举个简单的例子,一个整形数组A[],那么给A[]排序这个定义就相当于Unicode。那么是采用快排、堆排还是归并,用正序还是倒序排列结果,这些方法就相当于编码格式这些都是对这个定义的具体实现过程,但是方法不同。

因此,不论是UTF-8、GBK、Latin等,其还原的编码结果都是同一个Unicode编码。

 

四、Unicode和UTF-8的关系及转换过程

那么对于Unicode和UTF-8的关系,可以用上面的例子理解。不过真实情况应该是类似下面这样的。

比如"国"字的Unicode编码定义为 00000000 00000000 00110100 11000000 (假设)。

由于其低16位都是0,为了减少存储和传输这个字在字节上的浪费,就选择高16位来表示。同时由于UTF-8是可变长的,所以需要标识位来标识这个编码到底使用了几个字节。

所以 “国”字 对应的 UTF-8的编码应该是 11100011 10010011 10000000(加粗的是原编码的高16位)。

转换公式:1110xxxx(E0-EF) 10yyyyyy 10zzzzzz,显示标明的是标志位)。

以下附上UTF-8的编码方式:(引自wiki)

 

 

 

五、中文跨平台乱码及解决办法

有了以上知识的积累,我们可以分析为什么跨平台会出现乱码?明明好好的Unicode怎么就乱了呢?

那么很直观我们会想到应该是编码格式不兼容

对于windows平台,编码格式是GBK,对应的汉字是两个字节长度。对于Linux平台,编码格式是UTF-8,对应的汉字是3个字节。(这里都是默认情况)

那么我们还用上面 排序这个例子来解释。

比如现在Unicode用 {1,2,3}定义,GBK代表正序排列,UTF-8代表倒序排列。那么现在Unicode在GBK下的编码是{1,2,3},在UTF-8下的编码是{3,2,1}。

现在由GBK编码还原Unicode编码,那么正向解析GBK就是Unicode。而由UTF-8编码还原Unicode编码,需要逆向解析UTF-8编码。这都是和自身对应的。

但是如果一个把GBK编码误认为是UTF-8,那么逆向解析后的结果是{3,2,1}。首先这个结果不是原始的Unicode编码,那么其转换的结果不是我们需要的。其次,很可能这个编码结果在Unicode中还没有定义,可能会出现类似空格一样的空白符。

因此这就是跨平台中文乱码的原因,编码和解码方式出现了差别。

 

解决办法:

解决办法其实有很多种,根据自身应用的不同既可以选择在代码端进行编码的转换(比如java的 String str = new String(str.getBytes("GBK"), "UTF-8");),也可以在输入端进行编码格式的调整。

不过归结下来只有一点,即 如果当前输入是GBK编码,而你需要的又是UTF-8编码,那么:

1. 用GBK的解码方式转换成Unicode。

2. 使用UTF-8编码进行编码。

 

六、中文编码一些有趣的应用

这里我只想到了11游戏对战平台上面一些搞笑的名字(一不小心貌似暴露了什么。。不过很久不玩11了),后面想到其它还会更新的。

比如下面这个图:

蓝圈里面的玩家名字是正常显示的,为绿色。红圈里面的是蓝色,相当于突破了11客户端的限制显示了其它特殊颜色。

这个做法就是对应名字后面加上|r。这是一个转义符,合理的利用了11平台给用户开放的字符集并产生了特殊效果。所以这也是我开篇说的严格把控字符集是很难的,控制到不出错(比如系统乱码)已经挺好了。

 

转载请注明出处,谢谢~  http://www.cnblogs.com/xiaoboCSer/p/4175361.html

 

目录
相关文章
|
2月前
|
人工智能 运维 Serverless
AgentScope 拥抱函数计算 FC,为 Agent 应用提供 Serverless 运行底座
AgentScope推出Serverless运行时,直面AI Agent部署成本高、运维复杂、资源利用率低三大痛点。通过“按需启动、毫秒弹性、零运维”架构,实现低成本、高弹性、强隔离的智能体部署,助力多智能体应用从实验迈向规模化落地。
|
NoSQL MongoDB Docker
Docker Compose安装MongoDB,并向宿主机映射数据文件/配置文件/日志文件
本文为博主实践Docker Compose方式安装MongoDB记录,希望对大家有所帮助。
4178 0
|
9月前
|
编解码 Java 开发工具
【HarmonyOS Next之旅】DevEco Studio的安装与环境配置
本教程详细介绍了使用DevEco Studio进行OpenHarmony开发的全流程,包括下载与安装、环境配置、项目准备及实用技巧。首先,以Windows环境为例,说明了DevEco Studio的运行要求、下载和安装步骤;接着,通过设置环境变量和配置SDK完成开发环境搭建;然后,讲解了项目创建、预览器和虚拟机的使用方法;最后,分享了中文插件安装和简化工程目录栏等小技巧,帮助开发者高效上手OpenHarmony开发。
1128 0
|
2月前
|
CDN
阿里云 ESA 边缘加速(免费版) - 领取CDN加速免费套餐
阿里云ESA免费版全面开放!无论国际站或中国站用户,均可免费申请,享受无限流量CDN服务,大幅提升网站访问速度。
1265 7
|
SQL 缓存 Java
【吐血整理】MyBatis从入门到精通
本文介绍了 MyBatis 的使用指南,涵盖开发环境搭建、基础操作实例和进阶特性。首先,详细描述了 JDK 和 IDE 的安装及依赖引入,确保项目顺利运行。接着,通过创建用户表和实体类,演示了 CRUD 操作的全流程,包括查询、插入、更新和删除。最后,深入探讨了动态 SQL 和缓存机制等高级功能,帮助开发者提升数据库交互效率和代码灵活性。掌握这些内容,能显著提高 Java 编程中的数据库操作能力。
1673 4
|
人工智能 自然语言处理 文字识别
魔搭社区每周速递(8.18-8.24)
176个模型、35个数据集、85个创新应用、5篇应用文章
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
1395 9
|
敏捷开发 监控 Devops
提升软件测试效率:从手动到自动化的转型之路
在软件开发过程中,测试是确保产品质量和稳定性的重要环节。传统的手动测试虽然直观易懂,但随着项目规模的扩大和复杂度的增加,其效率和覆盖度已无法满足现代开发需求。本文探讨了从手动测试向自动化测试转型的必要性、实施步骤及注意事项,旨在帮助开发团队提高测试效率,保障软件质量。
258 0