转自:dbzhang800的 http://hi.baidu.com/cyclone/blog/item/d299af51e04aed868d543064.html
小结得好好呀!
字符集与编码问题小结
写在前面一直想整理一点文字编码相关的东西,却由于能力不够,始终不知道如何下手。看到论坛中编码一再被提起,终于决定尝试着整理一下。 --2010.05.30 编码的引入我们都了解,计算机只能存储2进制,也是就010100...,而无法存储“abc...”。当有人想把文字存储到计算机时,编码的故事就开始了... 既然计算机只能,只能存放二进制,那么我们就把“abc...”通过某种方式变成二进制不就解决了么? 比如,
哎,等等,为什么要用 0x41 表示 a 呢,如果有人用下面的方式怎么办?
ASCII有人用 0x41 代表a,有人用 0x81 表示。语言不通,不同的计算机无法交流。美国人很早发现了这种问题,为便于交流指定了编码标准,于是有了: ASCII (American Standard Code for Information)
ISO-8859-*ASCII 解决了美国人的问题,但很快,其他国家发现了这个编码不能满足自己国家的需要。法国、德国等国家暂且不说,英国都发现ASCII有问题:英镑符号“£”去哪儿了?现在好了, 既想与ASCII兼容,有要添加ASCII没有的文字符号,怎么办?扩展一下吧! 由于ASCII码只使用了7个二进制位,也就是说一个字节可以表示的256个数字中,它仅使用了0~127这128个码位,剩下的128个码位便可以用来做扩展,用来表示一些特定语言所独有的字符 因此对这多余的128个码位的不同扩展,就形成了一系列ISO-8859-*的标准。例如为英语作了专门扩展的字符集编码标准编号为ISO-8859-1,也叫做Latin-1。 ISO-8859-* (*代表1~11,13~16)共15个编码方案,解决了 拉丁字母的语言(主要是欧洲国家的语言),使用西里尔字母的东欧语言、希腊语、泰语、现代阿拉伯语、希伯来语等。 * 这些编码方案在当时解决了这些国家的问题,但不同的编码如同军阀割据,同一势力范围内交流没问题,但不能普遍通用。比如 \xA3 在使用 Latin-1 的国家看来,是英镑符号“£”,而在使用 Latin-2的国家看来,却是另一个符号 “Ł”。而且无法在一个文件内同时出现这两个符号。这个问题的解决,需要unicode。 ISO-2022 与 EUCISO-8859-* 解决了多数语言的编码问题,可是,汉语、日语及韩语字数众多,无法用单一个8位字符来表达,也就是无法通过类似 ISO-8859-*的方式解决。于是有了 ISO-2022 ISO-2022提供了这样一种技术,它能在一种字符编码中支持多种字符集,可以用8位或16位来表示一个文字(字符),是一种变长的编码,这样,就能表示中日韩的字符了。该编码还有个显著的特点,就是所有的字节都是以0开始。 ISO-2022 在日本用的比较普遍,在中国反倒是很少使用。尽管如此,还是用中文的 ISO-2022-CN 简单说一下: 在继续之前,我们先提一下GB2312:GB2312 中规定了汉字的区位码,同时指定 ISO-2022 (等同GB 2311) 为包装方式。 汉字“文”字在46区36位,用 ISO 2022 包装时,字节序列是:
前面说了,ISO-2022 在国内很少使用,那么国内用的什么编码方案呢? 这就是 EUC-CN: EUC (Extended Unix Code),是一个主要用于日文、韩文、简体中文 的多字节编码系统,它基于ISO-2020标准。它使用了一些兼容于ISO-2022区位码的94x94编码表,把每个区位加上0xA0来表示,以便兼容于ASCII。 今天通常说的 GB2312 编码都是指 EUC 包装的 GB2312 编码。 EUC-GB2312 与区位码的关系:
UnicodeUnicode是由于传统的字符编码方式的局限性而产生的,例如:
于是一个将所有国家所有语种的所有文字进行统一编码的方案开始了... Unicode与UCS1980年代,有两个组织分别开始开发适用于各国语言的通用码,但不久他们便发现了对方的存在。
ISO与Unicode是两个不同的组织,因此最初制定了不同的标准;但自从unicode2.0开始,unicode采用了与ISO 10646-1相同的字库和字码,ISO也承诺ISO10646将不会给超出0×10FFFF的UCS-4编码赋值,使得两者保持一致。最终,两者统一了抽象字符集(即任何一个在Unicode中存在的字符,在UCS中也存在),且最靠前的65535个字符也统一了字符的编码。 编码字符集与字符编码在传统意义上,没有字符集和编码的区分,比如GB2312、Latin1等都是既指代字符集又指代编码方案。
按照惯例,人们认为字符集和字符编码是同义词,但现代的编码方案 Unicode,没有遵循这种惯例。 Unicode 是一个字符集合,它给集合中的每个字符都指定一了个代号。 当我们要把这个代号存到计算机中时,需要把它变成一个字节的序列。不同的变换方式引入了 UTF
UTF
UTF 还涉及到字节序的问题。字节顺序标记(Byte Order Mark, 简称BOM)出现在Unicode流开端,说明编码类型。BOM是一个有点小聪明的想法。下面是常用的BOM:
GB18030
其他GBKGBK (Microsoft Code Page 936) 相传是微软公司在 EUC-GB2312 的基础上扩充了 Unicode 1.1 (GB13000.1-93) 而来, 最早出现于 Windows 95。没有对应的国家标准,只有一个《全国信息技术标准化技术 委员会 汉字内码扩展规范(GBK) 1.0》。
base64Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一 Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。 HZ将 EUC-GB2312 的各字节最高位去掉,再在前后分别加上转义字符,例如“文”: ~{ <0x4E> <0x44> ~} |