今天上课,老师想让我们清楚搞清楚HTML主要编码之间的关系,于是就开始在网上查资料。
结果,这个问题比我想象的复杂。
GBK
编码方式
经实际测试和查阅文档,GBK是采用单双字节变长编码,英文使用单字节编码,完全兼容ASCII字
符编码,中文部分采用双字节编码。
GBK 亦采用双字节表示,总体编码范围为 8140-FEFE,首字节在 81-FE 之间,尾字节在 40-FE
之间,剔除 xx7F 一条线。总计 23940 个码位,共收入 21886 个汉字和图形符号,其中汉字(包
括部首和构件)21003 个,图形符号 883 个。
全部编码分为三大部分:
1. 汉字区。包括:
a. GB 2312 汉字区。即 GBK/2: B0A1-F7FE。收录 GB 2312 汉字 6763 个,按原顺序排列。
b. GB 13000.1 扩充汉字区。包括:
(1) GBK/3: 8140-A0FE。收录 GB 13000.1 中的 CJK 汉字 6080 个。
(2) GBK/4: AA40-FEA0。收录 CJK 汉字和增补的汉字 8160 个。CJK 汉字在前,按 UCS 代码大
小排列;增补的汉字(包括部首和构件)在后,按《康熙字典》的页码/字位排列。
2. 图形符号区。包括:
a. GB 2312 非汉字符号区。即 GBK/1: A1A1-A9FE。其中除 GB 2312 的符号外,还有 10 个小写
罗马数字和 GB 12345 增补的符号。计符号 717 个。
b. GB 13000.1 扩充非汉字区。即 GBK/5: A840-A9A0。BIG-5 非汉字符号、结构符和“○”排列在此
区。计符号 166 个。
3. 用户自定义区:分为(1)(2)(3)三个小区。
(1) AAA1-AFFE,码位 564 个。
(2) F8A1-FEFE,码位 658 个。
(3) A140-A7A0,码位 672 个。
第(3)区尽管对用户开放,但限制使用,因为不排除未来在此区域增补新字符的可能性。
字形
GBK 对字形作了如下的规定:
1. 原则上与 GB 13000.1 G列(即源自中国大陆法定标准的汉字)下的字形/笔形保持一致。
2. 在 CJK 汉字认同规则的总框架内,对所有的 GBK 编码汉字实施“无重码正形”(“GB 化”);即
在不造成重码的前提下,尽量采用中国新字形。
3. 对于超出 CJK 汉字认同规则的、或认同规则尚未明确规定的汉字,在 GBK 码位上暂安放旧字
形。这样,在许多情况下 GBK 收入了同一汉字的新旧两种字形。
4. 非汉字符号的字形,凡 GB 2312 已经包括的,与 GB 2312 保持一致;超出 GB 2312 的部分,
与 GB 13000.1 保持一致。
5. 带声调的拼音字母取半角形式。
UTF-8
背景
互联网的普及,强烈要求出现一种统一的编码方式。UTF-8就是在互联网上使用最广的一unicode
的实现方式。其他实现方式还包括UTF-16和UTF-32,不过在互联网上基本不用。重复一遍,这里
的关系是,UTF-8是Unicode的实现方式之一。
UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根
据不同的符号而变化字节长度。
编码方式
UTF-8的编码规则很简单,只有二条:
1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字
母,UTF-8编码和ASCII码是相同的。
2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位
一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
下表总结了编码规则,字母x表示可用编码的位。
Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
ASCCI
背景
ASCII(American Standard Code for Information Interchange,美国信息互换标准代码)是一套
基于拉丁字母的字符编码,共收录了 128 个字符,用一个字节就可以存储,它等同于国际标准ISO/IEC 646。
编码方式
ASCII 包含了 33 个控制字符(具有某些特殊功能但是无法显示的字符)和 95 个可显示字符。共
收录了 128 个字符,用一个字节中较低的 7 个比特位(Bit)足以表示(27 = 128),所以还会空
闲下一个比特位,它就被浪费了。
ASCII 编码中第 0~31 个字符(开头的 32 个字符)以及第 127 个字符(最后一个字符)都是不可
见的(无法显示),但是它们都具有一些特殊功能,所以称为控制字符( Control Character)或
者功能码(Function Code)。这 33 个控制字符大都与通信、数据存储以及老式设备有关,有些
在现代电脑中的含义已经改变了。
规则
常见ASCII码的大小规则:0~9<A~Z<a~z。
1)数字比字母要小。如 “7”<“F”;
2)数字0比数字9要小,并按0到9顺序递增。如 “3”<“8” ;
3)字母A比字母Z要小,并按A到Z顺序递增。如“A”<“Z” ;
4)同个字母的大写字母比小写字母要小32。如“A”<“a” 。
几个常见字母的ASCII码大小: “A”为65;“a”为97;“0”为 48 [4]
。
URL编码
背景
url编码是一种浏览器用来打包表单输入的格式。浏览器从表单中获取所有的name和其中的值 ,将
它们以name/value参数编码(移去那些不能传送的字符,将数据排行等等)作为URL的一部分或
者分离地发给服务器。不管哪种情况,在服务器端的表单输入格式样子象这样:
theName=Ichabod+Crane&gender=male&status=missing& ;headless=yes
规则
URL编码遵循下列规则: 每对name/value由&;符分开;每对来自表单的name/value由=符分开。
如果用户没有输入值给这个name,那么这个name还是出现,只是无值。任何特殊的字符(就是那
些不是简单的七位ASCII,如汉字)将以百分符%用十六进制编码,当然也包括象 =,&;,和 % 这
些特殊的字符。
其中URL会有两次编码的过程
两次编码的原因:(重点)
一般的原因:解决服务器解码后乱码问题如果只进行一次encodeURI,得到的是UTF-8形式的
URL,服务器端通过
request.getParameter()解码查询参数(通常是iso-8859-1)就会得到乱码。
如果进行两次encodeURI,第一次编码得到的是UTF-8形式的URL,第二次编码得到的依然是UTF-8
形式的URL,但是在效果上相当于首先进行了一次UTF-8编码(此时已经全部转换为ASCII字符),再
进行了一次iso-8859-1编码,因为对英文字符来说UTF-8编码和ISO-8859-1编码的效果相同。在服
务器端,首先通过request.getParameter()自动进行第一次解码(可能是gb2312,gbk,utf-8,iso-
8859-1等字符集,对结果无影响)得到ascii字符,然后再使用UTF-8进行第二次解码,通常使用
java.net.URLDecoder("",“UTF-8”)方法。
两次编码两次解码的过程为:
UTF-8编码->UTF-8(iso-8859-1)编码->iso-8859-1解码->UTF-8解码,编码和解码的过程是对称的,所以不会出现乱码。