2.2. 支持多种衍生拉丁字母的字符编码:EASCII和ISO 8859

计算机出现之后,从美国发展到欧洲,而由于欧洲很多国家中所用到的字符中,除了基本的美国也用的那些拉丁字母之外,还有很多衍生的拉丁字母,而且是不同的国家用到的衍生字符都不太相同,所以欧洲人也遇到类似的问题,即如何将自己国家的那些字符,在计算机上显示出来,这就需要设计一个合理的字符编码,把所有这些字符都囊括其中。

即设计一个新编码标准,即兼容旧的ASCII的编码,又支持欧洲多个国家的那些衍生拉丁字母。

这样的标准有两个,一个是EASCII编码标准,一个是国际标准ISO 8859字符编码标准。

2.2.1. EASCII

将ASCII中的第八位也用上,那么就是8位的字符编码了,然后将EASCII中0xA0-0xFF这部分比ASCII码扩充出来的编码,用来表示表格符号、计算符号、希腊字母和特殊的拉丁符号等,这样就可以实现支持那么多欧洲的衍生拉丁字母了,也就是这个EASCII字符编码了。但是EASCII虽然解决了这些西欧语言的字符显示问题,但是对于其他语言显示,比如中文等,还是无法处理显示。

目前,很少使用EASCII,常用的是下面要介绍的第 2.2.2 节 “ISO 8859”编码标准。

2.2.2. ISO 8859

2.2.2.1. ISO/IEC 8859出现的背景

前面已经提到了,正是因为ASCII等字符编码中,没有包括欧洲很多国家所用到的一些扩展的拉丁字母,比如一些重音字母,带音标的等等,所以,才设计出新的这个ISO/IEC 8859来支持这些字符。

最终设计出来的ISO/IEC 8859的字符集,支持很多欧洲的语言,包括丹麦语、荷兰语、德语、意大利语、拉丁语、挪威语、葡萄牙语、西班牙语,瑞典语等。

2.2.2.2. ISO/IEC 8859的编码规则

我们已经知道了,ASCII是7位的单字节编码,其中0x20-0x7E的可见字符。

而ISO/IEC 8859,是在ASCII中的普通的可见字符(0x20-0x7E)的基础上,利用了ASCII的7位编码所没有用到的第8位,这样就编码范围就从原先ASCII的0x00-0x7F多扩展出了0x80-0xFF,其中的0xA0-0xFF部分,被ISO/IEC 8859编码所用到。

有别于ASCII的单个独立的编码规则,ISO/IEC 8859是一组编码规则的总称,其下包含了共15个字符集,即ISO/IEC 8859-n,其中n=1,...,11,13,...,16。

关于这15种字符集是如何分类的,可以参考:表 A.2 “ISO/IEC 8859编码标准中的15种字符集”

这15个字符集,每一个字符集,编码取值都是0xA0-0xFF,但是对于同一个值,不同字符集所对应的字符,都不太一样。

此处截取那15个字符集的其中一部分,以便更加直观的了解不同字符集的区别:

图 2.1. ISO/IEC 8859的15个字符集的部分比较

ISO/IEC 8859的15个字符集的部分比较

完整的字符表,请参见表 A.2 “ISO/IEC 8859编码标准中的15种字符集”

[注意] ASCII编码有时候也会写成ISO/IEC 8859-1编码

另外,需要注意的是,对于原先的美国的英文字母,即普通的英语,其虽然没有重音,音标等字母,但是由于其本身也还是包含在ASCII中,而ISO/IEC 8859-1包括了ASCII,所以,很多时候,对于英文字母来说,也仍会标明为ISO/IEC 8859-1编码。

2.2.2.3. ISO/IEC 8859的特点

对于ISO/IEC 8859所包含的全部字符,我们可以看到,对于基本的拉丁字母,那都是和ASCII一样的,因为其就是借用了ASCII中的0x20-0x7F这段的编码,对应的是那些常见的可显示的字符,而对于0xA0-0xFF这段空间,则是对于同一个值,不同的字符集中,对应着不同的符号。

对于ISO/IEC 8859的编码方式是设计了多个字符集,我们不难看出,其之所以这么编码,而不是像ASCII中每个编码值,都对应唯一的一个字符,那是因为,欧洲的全部所用的字符数很多,如果是对于全部的欧洲用的字符都用一个对应的值来表示,那么这剩下的0xA0-0xFF,甚至是0x80-0xFF,也都不够用的,因为0x80-0xFF128个值,当然不够表示欧洲那几百上千的不同国家的不同字符。

所以,才会去设计出这么15个字符集,然后对于同一个值,你用了ISO/IEC 8859-n,就表示对应的字符集中的那个特定的字符。

而上述做法的好处是,可以避免去用多个字节,比如两个字节(8×2=16位,可以表示最多2^16=65536个字符)去表示一个单独的字符,即节省了存放数据的空间。

但是缺点是,比如你写一篇文章,中间出现了多个不同语系的不同的字符,那么此文章如果用ISO/IEC 8859来编码的话,那么就无法单独存成某一种对应的字符集,即包含多个欧洲国家不同语系的特殊字符的数据,无法用ISO/IEC 8859的某一个单独的字符集来表示出来,即无法在同一个文章中支持显示不同语系的不同的字符。

当然,相对于亚洲字符,即中文,日文,韩文等字符来说,另外一个如果算的上是缺点的话,那就是没有把咱亚洲字符考虑进去。

正因此,字符编码,才会继续演化出更加通用的,包含了世界上所有的字符的字符编码标准:Unicode。

关于Unicode的详细解释请去看:第 2.4 节 “支持世界上几乎所有字符的字符编码:Unicode”

此处先来说说,其他几个和ISO/IEC 8859相关的内容。

2.2.2.4. ISO/IEC 6429

可以看到,对应的ASCII编码取值范围是0x0-0x7F,而ISO/IEC 8859虽然是8位的单字节的编码,但是只是除了ASCII的0x20-0x7E之外,只是指定了0xA0-0xFF,而中间还有一段的值,即0x80-0x9F,却没有定义。

对此部分,是对应的ISO/IEC 6429编码标准所定义的,此标准还定义了0x0-0x1F,即ASCII中的控制字符。

即,ISO/IEC 6429是专门定义对应的控制字符的,其中,0x0-0x1F部分称为C0控制(C0 control )字符,0x80-0x9F部分称为C1控制(C1 control)字符。

对应的C0 control部分,和ASCII编码重复定义了,但是两者含义都是一样的,所以编码规则并不冲突。

可以算是,在控制字符领域,ISO/IEC 6429在ASCII的C0 control的基础上,对于由ASCII的7位所扩展出的8位编码中的0x80-0x9F这部分,也做出了对应的定义。

简言之:

ISO/IEC 6429

= 0x0-0x1F + 0x80-0x9F

=7位编码ASCII中的0x0-0x1F + 扩展8位编码中的0x80-0x9F

=C0 control + C1 control

2.2.2.5. ISO 8859和ISO-8859的区别和联系

ISO 8859和ISO-8859,不是同一个东西。

注意,后者是ISO和8859中间带了一个小横短线的。

前者,ISO 8859是ISO/IEC 8859标准集合的简称,对应包含了 ISO/IEC 8859-n,其中n为除去2之外的1到16,这共15种字符集合。

ISO-8859,是ISO-8859-n的简称,是IANA根据ISO/IEC 8859-n的标准,加上对应的前面提到的普通的ASCII字符,和ISO/IEC 6429所定义的的控制字符,所制定的标准。

其中,由于ASCII中也包含了0x00-0x1F的控制字符,所以和ISO/IEC 6429中的C0控制字符重复了,但是两者定义都是一样的,所以从字符编码上来说,不会产生任何冲突。

因此,ISO-8859-n所以可以表示:

ISO-8859

= ISO-8859-n的简称

= ISO 8859-n + ASCII + ISO/IEC 6429

其中,n=1,...,11,13,...,16,共15种编码集合。

对应的,ISO 8859-1和ISO-8859-1两者当前也是不一样的,其区别也是:

ISO-8859-1

= ISO 8859-1 + ASCII + ISO/IEC 6429

= ISO/IEC 8859-1 + ASCII + ISO/IEC 6429

2.2.2.5.1. 原先的ISO 8859-1和我们常说的ISO 8859-1

原先的ISO 8859-1即ISO/IEC 8859-1,其编码前面已经介绍过了,此处只是给出对应的字符表:

图 2.2. ISO/IEC 8859-1字符集表

ISO/IEC 8859-1字符集表

其中绿色的部分,就是原先ISO 8859-1中未定义的部分。而这部分,之前已经解释了,是在另外的一个标准ISO/IEC 6429中定义的。

此处,需要注意的是,目前大家最常见的,提到最多的ISO 8859-1,实际多数都是指的是ISO-8859-1,即,是那个,既整合了0x20-0x1F这部分的普通的可以显示的ASCII字母(基本的拉丁字母),又包含了对应的控制字符( C0 control和C1 control),同时也包含了欧洲多数国家所用到那些字符(扩展的拉丁字母,即ISO/IEC 8859-1中所定义的那些字符)。

总结起来就是:

常说的ISO 8859-1

= 实际上是ISO-8859-1

= ASCII + ISO/IEC 6429 + ISO 8859-1

= ASCII + ISO/IEC 6429 + ISO/IEC 8859-1

= (0x20-0x1F) + (0x0-0x1F + 0x80-0x9F) + (0xA0-0xFF)

= ASCII中的可见字符 + C0和C1的控制字符 + 欧洲多国所用的扩展的拉丁字符