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

原文:【原创】通俗易懂地解决中文乱码问题(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

 

时间: 2024-10-31 02:59:09

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

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

原文:[原创]通俗易懂地解决中文乱码问题(2) --- 分析解决Mysql插入移动端表情符报错 'incorrect string value: '\xF0... 这篇blog重点在解决问题,如果你对字符编码并不是特别了解,建议先看看 < [原创]通俗易懂地解决中文乱码问题(1) --- 跨平台乱码 >. 当然,如果只是针对解决这个Mysql插入报错问题,本篇足够了.   一.定位错误   定位错误绝对是至关重要的一环.我建议遇到问题耐心分析一下比较好,毕竟"不是所有的牛奶都叫特仑苏

我在Spring中解决中文乱码的方法

解决|中文|中文乱码 软件环境:JDK1.4.2_09+Eclipse3.1+MS SQL SERVER200+SP3+JTDS1.0.2+Struts1.1+Hibernate3.0.5+Spring1.2.4. 由于刚开始学习这个Framework,所以很多东西也不是特别清楚,以前在JB环境下也没怎么遇到乱码问题.这次试了很多方法都不行,于是决定加个Fileter了,web.xml部分内容如下:  <filter>  <filter-name>SetCharacterEncod

用AS2解决中文ID3的乱码

解决|中文 flash如果MP3的ID3标签使用GB2312编码,那么在FLASH脚本输出时是乱码的代码1 var s:Sound=new Sound(this); s.loadSound("dxh.mp3",false); s.onID3=function(){ trace(this.id3.songname); } 输出结果是:¶¡Ïã» dxh.mp3的ID3v1的标签正确应该是songname="丁香花",看来FLASH在转码上出现了问题.我们来看看song

安装vsftpd解决中文乱码的问题

vsftpd-2.1.0 以上的版本已经解决了这个问题.最新版已经无须修改任何设置就可以很好支持各种字符集了.但如果你还在使用较低版本的vsftpd的话,哪么以下方法可以帮助你解决中文乱码的问题. 方法一: 补丁软件下载: http://www.cublohttp://www.aliyun.com/zixun/aggregation/9457.html">g.cn/u/2340/showart_428936.html 过程: 下载vsftpd-2.0.3.tar.gz,http://dow

CentOS 安装搜狗输入法以及解决中文乱码

一.安装搜狗输入法 首先要确保系统中已经安装了中文输入法. 如果你在安装系统时选择了中文,则中文输入法默认就会安装:如果你安装时选择了英文,则必须在安装时选择安装中文输入法,否则不会安装,即使你忘了选择,还是可以在装好系统之后安装.安装方法也非常简单,只需要联网后执行如下命令即可安装 #sudo yum install "@Chinese Support" 二.解决中文乱码 查看系统支持字符集: #locale -a 安装英文版默认的字符集配置为: # cat /etc/sysconf

c++ 编程问题-c++与java通信(socket TCP)c++用的默认的编码,java用的UTF-8 怎么解决中文乱码问题

问题描述 c++与java通信(socket TCP)c++用的默认的编码,java用的UTF-8 怎么解决中文乱码问题 c++代码如下,谁可以试着尝试一下,谢谢 #include #include #include #pragma comment(lib,"ws2_32.lib") void main() { //创建套接字 WORD myVersionRequest; WSADATA wsaData; myVersionRequest=MAKEWORD(1,1); int err;

itext生成pdf文件时中文不显示或者是乱码,这个怎么解决

问题描述 itext生成pdf文件时中文不显示或者是乱码,这个怎么解决 如题,我尝试了很多版本的jar包,而且itextasian.jar也在环境变量上配置了,但是中文还是显示不出来,各位大神,有解决的方法吗,这个已经困扰我一天了 解决方案 iText生成PDF文件(解决了中文乱码) 解决方案二: http://blog.sina.com.cn/s/blog_48bb8eb90100tt7p.html

怎么解决中文乱码

问题描述 怎么解决中文乱码 解决方案 解决方案二:LZ说的问题有点笼统,一般情况下就是把你的界面的编码格式设置成UTF-8,所有界面要统一,还有要把你的项目的编码格式,设置的和界面一致,另外就是些过滤器了解决方案三:比如我举一个实例:现在开发JEE的配置环境为Tomcat6.0,MyEclipse,Mysql安装Mysql数据库之前,要将字符集设置为gb2312(为中文简体);在使用MyEclipse新建网页时,头部声明字符集为setCharactorEncoding="gb2312"

web xml-jsp,servlet使用过滤器解决中文问题时如果输入英文反而出现乱码

问题描述 jsp,servlet使用过滤器解决中文问题时如果输入英文反而出现乱码 一:场景恢复 1,有一个html页面,其中有一个 标签,里面有一个text(name为content),一个submit.当单击submit时将text中的输入值传到servlet中进行输出. 2,有一个servlet,用来接收从html中传来的context值(text控件),然后进行输出. 3,有一个过滤器,具体详见代码部分. 4,有一个web.xml配置页面,用来配置servlet和Filter,具体详见代码