常用编码方式的基本概念以及Web编程中遇到的编码问题

 


前言:


 

  一直对ANSI、UNICODE、UTF-8,GBK等概念模糊,今天翻阅了网上相关的文章(数十篇),质量良莠不齐,甚至有些作者对于其中的概念也有所混淆。所以今天就做个笔记,写个清晰简单的文章,说明个中关系。也怕自己忘记了,再回来看看。

 


计算机篇:


 

  首先要知道两个单位,一个是Bit(位),一个是Byte(字节)。前者是的信息元,后者是信息存储的基本单位,8个位组成一个字节。

  ASCII码是用来对字符、数字、英文进行编码,采用10进制,且每个字符占一个字节。而GBK的出现扩充了ASCII,使其能用两位字符表示中文汉字和日文假名。其中GB2312是专门为简体汉字编码的。GBK和GB2312只是两个例子,这种扩充ASCII使用两个字节表示一个中文字符的方法统称为ANSI标准。

  而UNICODE之所以后来出现,是为了统一国际标准。UNICODE编码中,每个字符(不论中英文或符号)都是用两个字节来表示。为了解决UNICODE浪费存储空间和传输存在的缺点,基于UNICODE标准衍生出了UTF-8编码。UTF-8就是现在使用最广泛的国际编码标准。


Web篇:


 

  可能大家都有这样的经验,当使用FireFox浏览器时,在地址栏输入某一个带中文参数的网站时,浏览器会自动将参数转化为带%号的格式,比如将“测试”二字转化为为为%B2%E2%CA%D4。这样做是为了统一URL标准以及避免一些安全问题,于此同时,浏览器会将URL中不可控的特殊字符也转化为这种格式,俗称转化为URL格式,这样的编码方式叫做URL-encode。

  由于GB2312中,中文字符的表示方式为两个字节,一个字节8个位,而一位16进制数使用4个位。这样一算,一个中文字符使用4个16进制数,也就是2个2位16进制数,所以上面的例子中将“测试”转化为%B2%E2%CA%D4说明是转为GB2312格式而非UTF-8格式了。因为UTF-8中,一个中文字符用2~4个字节表示(大多数是3个字节)。这时候问题就来了,如果该网站页面设置使用UTF-8编码方式,如使用了HTML的<meta>标签:

<META http-equiv="content-type" content="text/html; charset=utf-8">

  或者PHP的header函数:

<?php
    header("content-type:text/html; charset=utf-8"); 
?>

  浏览器传输时将URL参数的中文转为GB2312格式,而解析的时候参考了了Header或者页面中的meta标签将内容按解码UTF-8格式来解码,就显示错误了。(这里header优先级高于meta,所以两者不一致的话参考header)

下面的表格说明了常用浏览器的预定转化方法:

  直接在地址栏输入URL

浏览器 path部分 query部分
编码种类 百分比编码 编码种类 百分比编码
IE UTF-8 GB2312
Firefox Opera UTF-8 GB2312
Chrome Safari UTF-8 UTF-8

 

 


如何解决:


 

  我们先来假设一下这个问题出现的场景:访问者直接用浏览器访问带中文参数的网站。这样的场景虽然不多,但是终究是无法避免的,假设你的朋友在QQ上发给你一个百度的搜索结果(“中文关键字”),这样必定会出现直接访问带中文参数的URL的情景,然后结果是出现了乱码。但是经我测试,现在百度已经解决了这个问题。

  首先,客户端(浏览器)是可以更改预定转化的字符集的,但我们应该从一个程序员的角度来解决这个问题,不是让访问者自己通过调整客户端来适应网页的编码。而且我们得知道一点:如果在一个页面通过脚本或者超链接的形式访问这样一个带中文参数的URL的话,所有浏览器在query部分的编码统一使用当前页面的编码方式。

  要解决问题,步骤①通过refer头判断是否是直接从地址栏访问的

          ②如果满足①,则通过User-Agent判断浏览器

          ③根据上面的表格做编码转化(比如PHP的mb_convert_encoding函数

 


关于其他:


 

  网页编程中会遇到其他的编码乱码问题,其实只要解决了之前说的那个问题(最蛋疼的问题),其他的问题只要保证“文件存储编码方法-html页面编码方法-header编码方法-数据库编码方法”四者一致即可。如果同一个网站的不同页面使用不同的编码方式的话,那么在链接跳转的使用使用JavaScript的ESCAPE函数(举个例子)转化而不通过浏览器就行了。

  还有一个问题就是如果通过外部网站的链接访问了带中文参数的地址,且两者的编码方式不同该如何解决?这个问题的解决方法我暂时也还没想出来,希望Web编程有经验的同学指教,同样的,如果文章有错误或纰漏也欢迎指出。

posted @ 2014-02-27 23:09  a1ison  阅读(1196)  评论(2)    收藏  举报