Character Encoding Summary

来源:互联网 发布:超市利润怎么算法公式 编辑:程序博客网 时间:2024/04/30 03:39
Brief Evolution History

Chinese Encoding Roadmap

Character Encoding System Hierarchy
   Character --> Code Point --> Encoding Scheme
  首先,我们需要确定对哪些字符进行编码;然后我们要分配给每个字符一个唯一的编码值;最后我们要知道如何表示这个编码值,是直接存储这个编码值,还是对编码值进行变化(比如,UTF-8,UTF-16)。
I.ISO 

1. ASCII
 全称是American Standard Code for Information Interchange。它是由美国标准协会(最初名称是American Standards Association--ASA, 后来改名为American Nation Standards Institute--ANSI)上个世纪50年代开发。它是一个英文字表系统的字符编码体系。总共128个字符,包括1)数字0-9;2)字母a-z,A-Z;3)一些标点符号;4)控制符号;5)空格。


2. ISO 646

ISO 646对ASCII进行扩展,对非英语国家的字符进行编码,但仍然是7位字符的字符集。英语字母和数字部分,为所有国家相同外,有些使用字母的国家,可按照实际需要,把 ISO 646 修改,以定出该国的字符标准。下面这张图显示了ISO 646的字符集。灰色阴影部分随地区变化而变化。


下表列出了不同国家的变化


中国基于ISO-646的标准是GB1988-80,主要变化就是0x24的字符是人民币的符号“¥”,以及0x7E是"-".

3. ISO 2022

1) ISO 646虽然是对ASCII进行了扩展,但毕竟是7位编码,其扩展是有限的。而这时的通信领域的协议采用了第8位做校验纠错用途,但是,对于计算机内存来说,校验纠错变得不是必要。因此8位字符编码逐渐出现,用来表示比ASCII码更多的字符。为此,1971年公布的ECMA-35标准,用来规定各种7位或8位字符编码应当遵从的共同规则。随后ECMA-35被采纳为ISO 2022. 

英语可用7位编码储存,而其他使用拉丁字母、希腊字母、西里尔字母、希伯来字母等的语文,由于只使用数十个字母,传统上均使用8位编码的ISO/IEC 8859标准来表示。但由于汉语、日语及朝鲜语字数众多,无法用单一个8位字符来表达,故需要多于一个字节来代表一个字。于是,ISO 2022就设计出来让汉语、日语及朝鲜语可以使用数个8位编码的字符来示。

ISO 2022使用“转义符串”(Escape sequence)。转义符串由1个“ESC”字符(0x1B),再由两至三个字串组成。此标记代表它后面的字符,属于下表字符集的文字。

2)ISO 2022定义了一规则,如何进行7位或者8位编码,但是没有具体定义某个字符集是如何编码。 ISO 8859则是在ISO 2022基础上定义了一系列字符集的编码标准。
  • ISO/IEC 8859-1 (Latin-1) - 西欧语言
  • ISO/IEC 8859-2 (Latin-2) - 中欧语言
  • ISO/IEC 8859-3 (Latin-3) - 南欧语言
  • ISO/IEC 8859-4 (Latin-4) - 北欧语言
  • ISO/IEC 8859-5 (Cyrillic) - 斯拉夫语言
  • ISO/IEC 8859-6 (Arabic) - 阿拉伯语
  • ISO/IEC 8859-7 (Greek) - 希腊语
  • ISO/IEC 8859-8 (Hebrew) - 希伯来语(视觉顺序)
  •       ISO 8859-8-I - 希伯来语(逻辑顺序)
  • ISO/IEC 8859-9(Latin-5 或 Turkish)- 它把Latin-1的冰岛语字母换走,加入土耳其语字母。
  • ISO/IEC 8859-10(Latin-6 或 Nordic)- 北日耳曼语支,用来代替Latin-4。
  • ISO/IEC 8859-11 (Thai) - 泰语,从泰国的 TIS620 标准字集演化而来。
  • ISO/IEC 8859-13(Latin-7 或 Baltic Rim)- 波罗的语族
  • ISO/IEC 8859-14(Latin-8 或 Celtic)- 凯尔特语族
  • ISO/IEC 8859-15 (Latin-9) - 西欧语言,加入Latin-1欠缺的芬兰语字母和大写法语重音字母,以及欧元(€)符号。
  • ISO/IEC 8859-16 (Latin-10) - 东南欧语言。主要供罗马尼亚语使用,并加入欧元符号
3)ISO 2022的亮点就是支持中、日、韩的文字。
  • ISO-2022-JP. A widely used encoding for Japanese. Starts in ASCII and includes the following escape sequences ESC ( B to switch to ASCII (1 byte per character)
ESC ( J to switch to JIS X 0201-1976 (ISO/IEC 646:JP) Roman set (1 byte per character)
ESC $ @ to switch to JIS X 0208-1978 (2 bytes per character)
ESC $ B to switch to JIS X 0208-1983 (2 bytes per character)
  • ISO-2022-JP-1. The same as ISO-2022-JP with one additional escape sequence ESC $ ( D to switch to JIS X 0212-1990 (2 bytes per character)
  • ISO-2022-JP-2. A multilingual extension of ISO-2022-JP. The same as ISO-2022-JP-1 with the following additional escape sequences [1] ESC $ A to switch to GB 2312-1980 (2 bytes per character)
ESC $ ( C to switch to KS X 1001-1992 (2 bytes per character)
ESC . A to switch to ISO/IEC 8859-1 high part, Extended Latin 1 set (1 byte per character) [designated to G2]
ESC . F to switch to ISO/IEC 8859-7 high part, Basic Greek set (1 byte per character) [designated to G2]
  • ISO-2022-JP-3. The same as ISO-2022-JP with three additional escape sequences ESC ( I to switch to JIS X 0201-1976 Kana set (1 byte per character)
ESC $ ( O to switch to JIS X 0213-2000 Plane 1 (2 bytes per character)
ESC $ ( P to switch to JIS X 0213-2000 Plane 2 (2 bytes per character)

  • ISO-2022-JP-2004. The same as ISO-2022-JP-3 with one additional escape sequence      
                   ESC $ ( Q to switch to JIS X 0213-2004 Plane 1 (2 bytes per character)
  • ISO-2022-KR. An encoding for Korean.  
                   ESC $ ) C to switch to KS X 1001-1992,[2][3] previously named KS C 5601-1987 (2 bytes per character) [designated to G1]
  • ISO-2022-CN. An encoding for Chinese. 
                    ESC $ ) A to switch to GB 2312-1980 (2 bytes per character) [designated to G1]
ESC $ ) G to switch to CNS 11643-1992 Plane 1 (2 bytes per character) [designated to G1]
ESC $ * H to switch to CNS 11643-1992 Plane 2 (2 bytes per character)
  • ISO-2022-CN-EXT. The same as ISO-2022-CN with six additional escape sequence
                    ESC $ ) E to switch to ISO-IR-165 (2 bytes per character) [designated to G1]
ESC $ + I to switch to CNS 11643-1992 Plane 3 (2 bytes per character) [designated to G3]
ESC $ + J to switch to CNS 11643-1992 Plane 4 (2 bytes per character) [designated to G3]
ESC $ + K to switch to CNS 11643-1992 Plane 5 (2 bytes per character) [designated to G3]
ESC $ + L to switch to CNS 11643-1992 Plane 6 (2 bytes per character) [designated to G3]
ESC $ + M to switch to CNS 11643-1992 Plane 7 (2 bytes per character) [designated to G3]

    4) 按照标准,汉字编码以下面的形式出现:
       逃逸字符串 + 转换控制符(转为逃逸字符串代表的字符编码) + 汉字国标码( 区位码H+20H,H表示十六进制) +转换控制符(转为ASCII,是SI,十六进制是0F).
    
   例如, 按照GB2312给"交换"编码:
      "交"的区位码是2927,十六进制是1D1B. 对应国标码是3D3B.
      “换”的区位码是2727,十六进制是1B1B. 对应国标码是3B3B.
      ESC $ ) A表示接下来的编码符号GB2312标准。GB2312的转换控制符是S0,十六进制是0E.
     所以编码是:
     1B 24 29 41 0E 3D 3B 3B 3B 0F.
     "1B 24 29 41" 就是“ESC $ ) A”对应的ASCII 编码; "3D 3B 3B 3B" 就是“交换”的GB2312编码; “0E” 是转换字符,和"ESC $ ) A"表示它后面的字符是GB2312编码汉字‘; "0F"也是控制字符,表示后面的字符是ASCII编码.
    
    

4. ISO 10646 和 Unicode
1. 简述
ISO10646,定义了通用字符集(UCS--Universal Character Set),包含了已知语言的所有字符集。用一个标准来处理所有的字符,使得字符编码变的统一和简单。ISO 10646 定义了一个 31 位的字符集. 最经常使用的字符在第一平面(0x0000--0xFFFD),这个 UCS 的 16位子集称为 基本多语言面 (Basic Multilingual Plane, BMP). 被编码在 16 位 BMP 以外的字符都属于非常特殊的字符(比如象形文字), 且只有专家在历史和科学领域里才会用到它们. 按当前的计划, 将来也许再也不会有字符被分配到从 0x000000 到 0x10FFFF 这个覆盖了超过 100 万个潜在的未来字符的 21 位的编码空间以外去了.
用"U+XXXX"来表示一个字符的编码. 比如U+0041表示字母“A”. 值"XXXX"称为对应字符的代码点(code point).

2. 和Unicode的关系
 历史上, 有两个独立的, 创立单一字符集的尝试. 一个是国际标准化组织(ISO)的 ISO 10646 项目, 另一个是由(一开始大多是美国的)多语言软件制造商组成的协会(Unicode Consortium)组织的 Unicode 项目. 幸运的是, 1991年前后, 两个项目的参与者都认识到, 世界不需要两个不同的单一字符集. 它们合并双方的工作成果, 并为创立一个单一编码表而协同工作. 两个项目仍都存在并独立地公布各自的标准, 但 Unicode 协会和 ISO/IEC JTC1/SC2 都同意保持 Unicode 和 ISO 10646 标准的码表兼容, 并紧密地共同调整任何未来的扩展

3. 组合字符和实现层次
UCS-2 编码了很多组合字符(combining character),也称为表示浮动发音符的无间距标记。在包括印度语、泰国语、阿拉伯语和希伯来语在内的多种文字体系中,这些字符是必需的。在拉丁文、西里尔文和希腊文中,组合字符被用来生成字符。但是,组合字符的存在也产生了同一文本出现另一种编码的可能性。虽然这种编码没有歧义性,而且也保护了数据完整性,但是处理含有组合字符的文本就更加复杂了。为了适应那些选择不处理组合字符的应用程序,ISO10646 定义了下列实现级别:

1) Level 1   不支持组合字符和 Hangul Jamo 字符 (一种特别的, 更加复杂的韩国文的编码, 使用两个或三个子字符来编码一个韩文音节).

2) Level 2    类似于级别1, 但在某些文字中, 允许一列固定的组合字符 (例如, 希伯来文, 阿拉伯文, Devangari, 孟加拉语, 果鲁穆奇语, Gujarati, Oriya, 泰米尔语, Telugo, 印.埃纳德语, Malayalam, 泰国语和老挝语). 如果没有这最起码的几个组合字符, UCS 就不能完整地表达这些语言.

3)Level 3    支持所有的 UCS 字符, 例如数学家可以在任意一个字符上加上一个 tilde(颚化符号,西班牙语字母上面的~)或一个箭头(或两者都加).

4. 编码体系(Encoding Schemes)
标准赋予每个字符唯一的整数值,这个值称为代码点(code point).如何在计算机中表示这个代码点,就是编码方式.
1. UCS-2
用固定的两个字节表示一个代码点,这两个字节的值就等于代码点。比如“A”的代码点是"0x0041",其UCS-2编码就是"0x0041". 这种编码方式显然不能给所有的UCS字符编码,已经被UTF-16取代.

2. UCS-4
用固定的四个字节表示一个代码点,这四个字节的值就等于代码点。比如“A”的代码点是"0x0041",其UCS-4编码就是“0x0000 0041”.

3. UTF-8
即 UCS Transformation Format. 它是变长的编码方式,基本规则是:
1) U+0000到U+007F之间的UCS字符采用单字节编码0x00到0x7F,和ASCII兼容.
2) 所有大于U+007F的UCS字符采用若干个字节的编码方法,每个字节的高位都是1,因此所有ASCII字符都不会出现在其中。
3) 多字节的第一个字节的范围是0xC0到0xFD,这个字节前面的连续1的个数表示多少个字节出现在这个字符编码中。它后面的字节的范围是0x80到0xBF,也就是都是以10开头的字节.
4) 所有(2**31)UCS字符能被编码.
5) UTF-8编码的字符理论上最多六个字节,16位的基本平面的字符最多3个字节.
6) 保留代码点的字节的大端顺序(Big Endian)
7) 字节0xFE,0xFF没有被编码,它们是保留来表示字节序(Byte Order Mark)

下表的字节序列被用了表示一个字符,使用哪个字节序列由字符的代码点(code point)的字节数来决定.
U+00000000 – U+0000007F:
0 xxxxxxx
U+00000080 – U+000007FF:
110 xxxxx 10xxxxxx
U+00000800 – U+0000FFFF:
1110 xxxx 10xxxxxx 10xxxxxx
U+00010000 – U+001FFFFF:
11110 xxx 10xxxxxx 10xxxxxx 10xxxxxx
U+00200000 – U+03FFFFFF:
111110 xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U+04000000 – U+7FFFFFFF:
1111110 x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

例子:
对U+6C34(表示中文"水")进行UTF-8编码
i. U+6C34 是  范围U+00000800-U+0000FFFF之内,所有使用的序列是“1110xxxx 10xxxxxx 10xxxxxx”
ii. 0x6C34就是“0110 1100 0011 0100”,把这个比特序列从左到右填充到上面序列中,填充时也是从左到右,替换上面的“x”,得到
“ 11100110 10110000  10110100”,就是对于U+6C34的UTF-8编码,写成十六进制就是0xE6B0B4.

4. UTF-16
UTF-16也是变长编码方式,使用一个或者两个16位的单元来编码. 其编码规则是:
i) 从U+0000到U+D7FF已经从U+E000到U+FFFF之间基本平面内的字符用一个16位(就是两个字节)的编码,其值就等于字符的代码点(code point).
ii)从U+10000到U+10FFFF的扩展平面内的字符,采用两个16位的编码单元,称为代理对(surrogate pairs),前一个称为前代理(lead surrogate),后一个称为后代理(trail surrogate)
  得到代理对的过程
     1)代码点减去0x010000后得到一个20位比特的二进制序列值,这个20位比特的值将被分为两部分来计算前代理和后代理
     2)第一部分高位的10个比特加上0xD800得到前代理
     3)第二部分地位的10个比特加上0xDC00得到后代理
iii) 字节序上可以采用大端(以FE,FF开头)或者小端(以FF,FE开头)

 例子:
 对U+6C34(表示中文"水")进行UTF-16编码
   它在基本平面内,直接使用一个16位单元编码. UTF-16BE = 6C,34. UTF-LE = 34,6C

对U+1D22E进行UTF-16编码
 在扩充平面内,使用两个16位单元编码
   1) v = 0x01D22E - 0x010000 = 0x00D22E = 1101 0010 0010 1110
   2) vh = v>>10 = 11 0100 = 0x34 
       sl = vh + 0xD800 = 0xD834
   3) vl = v & 0x3FF =  10 0010 1110 = 0x22E
       st = vl + 0xDC00 = 0xDE2E
  所以,UTF-16BE = D8,34,DE,2E
            UTF-16LE = 34,D8,2E,DE

0 0
原创粉丝点击