字符串的编码标准(字符串编码(charset,encoding/decoding)问题原理)
编码问题很重要 ,关于编码问题的文章也很多 。我本来没有兴趣重复这个主题 。
一个朋友问我有没有比较好的编码介绍文章 。我记得以前看过几篇很不错的 ,但是当时搜索到的时候 ,就比较费劲 ,一时想不起来 。于是 ,我就说 ,我攒一篇好了 。
---------------------------------------
编码无处不在 。Database, file, editor, IDE, compiler, browser 。
代码(比如java, jsp, asp, php, python, ruby etc)里面的字符串比较麻烦 ,涉及到editor, compiler, interpreter等等 。
所以 ,我的做法是 ,从来不在代码里面直接写字符串资源 ,尤其是双字节编码的字符串资源 。
都是把字符串资源分离到一个单独的资源文件里面 。这样 ,只需要照管这个文件的编码就够了 。
需要注意的一点是 ,文件里面 、数据库里面 、网络传输需要的数据,都是byte[] 。
以下的讨论 ,不涉及代码里面的字符串编码问题。只讨论系统运行起来之后 ,各部分之间的编码问题 。
先说Java 。
JVM里面的任何字符串资源都是Unicode,就是说 ,任何String类型的数据都是Unicode编码。没有例外 。既然只有一种编码 ,那么 ,我们可以这么说 ,JVM里面的String是不带编码的 。String相当于 char[] 。
JVM里面的 byte[] 数据是带编码的 。比如 ,Big5 ,GBK ,GB2312 ,UTF-8之类的 。
一个GBK编码的byte[] 转换成 String ,其实就是从GBK编码向Unicode编码转换 。
一个String转换成一个Big5编码的byte[] ,其实就是从Unicode编码向Big5编码转换 。
所以 ,Unicode是所有编码转换的中间介质 。所有的编码都有一个转换器可以转换到Unicode ,而Unicode也可以转换到其他所有的编码 。这样构成了一个总线结构 。
比如,如果总共有10种编码 ,那么只需要 10 + 10 = 20个转换器就够了 。如果要是两两直接转换 ,那么,需要的转换器数量是一个组合数字 ,需要90个转换器 。
一个系统的不同部分 ,都有自己的编码。比如 ,数据库 ,文件 ,JVM ,浏览器这4个部分 。
在这些部分之间数据交换的地方 ,就会出现编码问题 。比如 ,数据库和JVM之间 ,文件和JVM之间 ,浏览器和JVM之间。这些问题的原理都是相通的 。
编码问题最容易处理的地方是文件和JVM之间 。文件IO API带有encoding 参数 ,请自行查阅 。
最不容易出现编码问题的地方是数据库和JVM之间 。这应该是数据库JDBC连接的基本功能 。本文不专门进行讨论 。
最容易出问题的地方是浏览器和服务器JVM之间(其实 ,代码里面的字符串更容易出问题,不过 ,我已经事先声明 ,本文不讨论代码中的字符串编码) 。下面主要讨论这块浏览器和服务器JVM之间的编码问题 。
我们把浏览器编码叫做 Browser_Charset,把JVM编码叫做JVM_Charset(通常等于服务器系统编码) 。
当浏览器的数据过来的时候 ,是一个带有Browser_Charset的byte[] 。
如果用户处理程序需要一个String类型的数据 ,那么JVM会好心好意地把这个byte[]转换成String 。使用的转换器是 JVM_Charset -> Unicode 。
注意 ,如果这个时候 ,Browser_Charset 和 JVM_Charset并不相等。那么 ,这个自动转换是错误的 。
为了弥补这个错误 。我们需要做两步工作。
(1) Unicode -> JVM_Charset ,把这个String 转换回到原来的 byte[] 。
(2) Browser_Charset -> Unicode ,把这个还原的byte[]转换成 String 。
这个效果 ,和直接从HTTP Request取得byte[] ,然后执行 (2) Browser_Charset -> Unicode 的效果是一样的 。
如果在Request里面设置了CharacterEncoding ,那么POST Data参数就不需要自己手工转换了 ,web server的自动转换就是正确的 。URL的参数编码还涉及到URL编码 ,需要考虑的问题多一些,没有这么简单 。
JVM把数据发到浏览器的时候 。也需要考虑编码问题 。可以在Response里面设置 。另外 ,HTML Meta Header里面也可以设置编码 ,提醒Browser选择正确编码 。
有些语言的VM或者解释器的字符串编码可能不同 。比如,Ruby 。不过 ,编码转换原理都是一样的 。
That is all.
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!