我保证这是最后一篇了,而且这次的内容绝对都是很具体的,具体得连每篇博客开头例行的摘要我都不知道该写什么了! 典型乱码乱码、问号、方块用文本编辑器打开一个文件,如果编码不兼容,有时候会看到 前文中我们有说到实用的很多编码方式都用的是变长字节编码,很多字节都要结合它的上下文去解释才是对的。例如:用UTF-8的算法去解析GBK的文件,就很容易发些这么些种情况:
反过来看,用GBK的算法去解析UTF-8的文件其实也差不多,遇到第一种情况在显示的时候可能就用问号代替,而遇到第二种情况就是出现一些风马牛不相及的杂乱文字。 方块其实和问号本质上一样的,但方块在现代浏览器里还有个很常见的情况,就是一个字符的编号在字体当中并没有定义,于是在排版和渲染的适合“智能”地用一个方块来表示它了。看到方块可以结合上下文,如果上下文当中的非英字符显示正确的,那么方块可能是一些特殊符号,比如Emoji。 在写服务端程序的时候要小心处理“半个字符”的问题,例如我们在前级对超长的数据进行截断处理,刚好截断掉一个变长编码的字节序列,就会出现“半个字符”。一般半个字符都是铁定会乱码,一些容错比较差的程序甚至会挂,比如一些做的不好的PHP的C扩展,严重的时候会出core。所以程序不懂编码就别瞎截,甚至考虑到某些语言文字里的组合字符,就是知道编码也别瞎截(真是细思恐极); BOM
BOM(Byte-Order Mark,字节序标记)是Unicode码点 UTF-8本身是没有字节序的问题的(因为它是以单个字节为最小单位),但是Windows里面很多编辑器(比如记事本)会多此一举的在UTF-8文件开头加入 如果你的PHP文件里面有一个这东西你就倒了大霉了,可能会:
于是建议在Windows上做开发的同学,一定要选择“使用UTF-8无BOM格式”保存, 锟斤拷乱码之所以叫乱码,就是因为它是“乱”的。但是乱码当中最出名的就是“锟斤拷”,他出现次数太多了以至于看起来根本就没那么“乱”。这就纳了闷了,为什么全中国的网站乱码里面都会有这个? 原因是,在将一些国家语言编码体系,比如GB、BIG-5、EUC-JP等,转换为Unicode的过程中,多少有一些字符是不在Unicode中的(比如一些偏旁部首在Unicode里是后来才收录的),甚至它本身在原来的编码体系里面就是非法字符的情况。 Unicode规定了 要避免锟斤拷一个重要的点就是尽量减少程序当中的编码转换。比如输入是UTF-8,但是一个旧的模块是GBK,把UTF-8转成GBK交给旧的模块处理,处理过程中旧模块多多少少有些BUG的可能,再转回来的时候就容易锟斤拷了。一个项目的源代码在团队里面被不同的人(他们编辑器配置不尽相同)开来开去,存来存去,也很容易出现锟斤拷。 烫烫烫、屯屯屯这个和编码转换其实没啥关系,在VC的DEBUG模式下,会把未初始化的栈内存全部填成 而用GBK编码的话, URL Encode和Base64URL EncodeURL Encode又称为“百分号编码”它主要用来在URI里面将特殊字符进行转义,因为像 对于ASCII字符的编码很简单就是用 对于非ASCII字符,将它的每个字节进行相同规则的转换,例如中文“编码”的Unicode char code是 可以看出,URL Encode编码非ASCII字符的时候,结果与使用的字符编码有关。因此在页面上提交表单、发起Ajax请求等操作的时候需要注意编码。浏览器会按照当前页面所使用的字符编码对表单体提交进行URL Encode,但使用JavaScript的 表单提交的时候编码是非常非常重要的,一旦错了服务端解开数据的时候就会跪。比如Github在它们的搜索表单里面放了一个 在JavaScript中使用 Base64Base64是一种用可见字符表示二进制数据的方法。它用了64个可见字符 Base64的编码程序非常简单,由于64=2^6,6和8的最小公倍数是24,也就是3byte,因此对输入数据以3byte为一个单位,查表把它转换成4个可见字符。 如果输入末尾不足3byte,那就补足,补1个byte就在输出末尾添加一个 Base64经常用来在一些文本协议里面保存二进制数据,比如HTTP协议,或者电子邮件的附件啊什么的。同时因为它的输出对于人类而言不可读,可以起到一些“混淆加密”的作用,事实上就有修改64个字符的排布来做一个变形Base64实现一个简单加密算法的例子。从密码学的角度看它基本上没什么强度可言,但是足够简单,可以起到防君子不防小人的作用。 由于一个字符只能编码6bit,自身却占了8bit,8/6=1.33,因此使用Base64来表示数据的时候会浪费1/3的体积。对于在CSS里面用Base64的data-url方式表示图片,用之前不妨简单估算一下,膨胀的体积和一个HTTP请求头比起来会相差多少,说不定涨太多了已经损失掉省一个请求的收益了。 尾声终于整个系列都要结束了,理论的也好,实用的也好,基本上我觉得该说的都说了,要是以后再遇到乱码,一定会很快知道问题所在。 最后还是要佩服并感谢一下ISO和Unicode联盟,做了这么伟大的事情将全世界的语言文字统一收录和编码,而这当中包括了那么多我们根本没听说过的奇怪的语言文字。正是因为他们的努力奠定了互联网是一个无国界的世界,每天我们都能通过它获得来自任何地方任何语言的信息。 哦,我上面说的不是某国的互联网。 |
|