序:曾经在写一个课程设计(jsp+js+servlet)时遇到了乱码问题,当时知道是编码问题,但由于对编码的不了解,被搞得焦头烂额。前段时间,抽空研究了一下流行的编码,在这里总结一下。在这篇文章中,并不会包含太多非常细节的东西,也不要求涉及非常广,而是注重各个编码之间的关系。广告:这个话题起初是作为开源沙龙的一个小演讲开始的,在这里可以看到当时的PPT,也可以下载下来。
第一章:万物伊始 - 字符编码之定义
在研究每个问题之前,第一步总是要定义问题,给出研究范围。那么我们来看看维基百科上是如何定义字符编码(Character Encoding)的:A character encoding system consists of a code that pairs each character from a given repertoire with something else. 其实说白了,字符编码就是给定一个字符集(可能是英文字母或者汉字,日文的假名,阿拉伯数字)和“某些其他东西”之间的一个一一对应,这里“某些其他东西”一般是个整数。
为了叙述方便,character encoding也有一些同义词,比如:character map(字符映射), character set(字符集), code page(代码页).
第二章:远古时代 - 最简单的字符编码
提到最简单的字符编码,我想你我都非常熟悉:ASCII(American Standard Code for Information Interchange)。这里的编码涉及到最原始的思想,就是非常简单的为每一个字符分配一个数字。当时采用的是单子节编码,用8位二进制来表示,其实只用了7位,从0x20到0x7F。其中0x20之前的为Control Character(控制码),如0x0A为Line Feed,即linux系统中的换行。
第三章:各自为政 – 编码系统的混乱
在这一章中的两种编码都还是采用8位二进制编码,但是为了和ASCII编码保持兼容,前128个与ASCII保持一致,只是利用了后128个位置,现在看来这么办这个世界还是比较美好的,但问题是:不是一个人想到了这个解决方法,不同的后128个位置的处理方法不同导致了不同的编码方法,编码系统的混乱开始了。
1 ,ISO/IEC 8859-n 系列ISO/IEC 8859-n系列包括ISO/IEC 8859-1,ISO/IEC 8859-2...ISO/IEC 8859-16,共有15部分,不包括已经废除的ISO/IEC 8859-12。其中,这个系列中ISO/IEC 8859-1最为常用,多用在西欧地区,比如法国、德国、挪威等等。你时常可以在eclipse中发现这种编码。
下图为ISO/IEC 8859-1中后128个位置的编码(此图来自维基百科的ISO/IEC 8859-1词条页面)。
欧洲人民基本上满意了。
2 ,Windows code page 系列微软很喜欢自己搞一套东西,通常都是不符合标准的,似乎他要传递的信号是:我就是标准。
Windows Code Page是存在于windows操作系统中的编码系列,这个系列中有很多编码方式,大家可以去维基百科页面查询。
在这里我们先介绍windows code page 437,我想你对下图肯定不陌生:
code page 437是IBM PC上使用的一套编码标准。
还有一种code page我们会接触到,就是windows code page 1252,因为它相当与windows系列中的ANSI编码,在使用windows记事本保存文件时,可以在“编码”下拉菜单中看到,如下图:
其实并不是所有的windows code page都是8为二进制编码,比如:
Windows Code Page的非8位编码:
Windows 932:日文
Windows 936:简体中文,即GBK
Windows 949:韩语
Windows 950:繁体中文,即Big5
Windows 1200:Unicode (UTF-16LE)
Windows 1201:Unicode (UTF-16BE)
Windows 65001:Unicode (UTF-8)
3,中文汉字编码系列
美帝国主义万万也没想到中国的劳苦大众也会用上计算机。
很显然,如果给汉字编码,8位二进制肯定是不够的。较早的汉字编码应该算是GB 2312,即国家标准(Guojia Biaozhun),它包括6763个汉字、标点符号、日文假名(怎么会有日文假名?)、希腊字母、有拼音标注的汉字(好东西,但是估计花了不少力气),比较悲剧的是即使这样,还有很多奇怪地名、人名未包含在其中。
然后就出现了GBK,GBK是GB2312的扩展,其中K代表扩展(Kuo Zhan),最终大约2000多个位置,新增了很多符号和繁体字。
下面简单介绍一下GBK的编码分布。
第一部分:为了和ASCII保持兼容,原来在ASCII中的字符编码保持不变。
第二部分:用两个字节表示汉字,但是,为了识别的方便,这两个字节的第一个字节不能小于0x7F。准确来说,第一个字节的范围为0x81~0xFE,第二个字节的范围为0x40~0x7E和0x80~0xFE。
为了保持整个中华民族文化的传承,又将GBK做了扩展:GB18030,其中在GBK的基础上,添加了一些少数民族的字。GB系列还有一个叫法:DBCS,即Double Byte Character Set。
至此,我想你应该已经理解了“一个汉字两个字节”的含义了。根据GB系列的编码方式,总是可以通过检查编码的第一个字节是否大于0x7F来判断这个字符是不是个汉字。
另外,由于GB系列同样对逗号等这类标点符号进行了编码,所以又出现了全角、半角之分。
(未完待续)
敬请期待“字符编码浅谈”的第二部分:Unicode一统天下。另注,文章中的引用链接等会在此系列的第二篇文章中给出。