计算机技术领域的复杂性很多或者说大多数都是在保持前向兼容性的需求下增加的复杂性,两个最明显的例子就是intel的cpu体系结构和字符的编码,本文不再说cpu方面的东西而着重说一下编码,关于intel cpu的发展随便找点资料都说得很详细,而关于字符编码的资料却都很晦涩难理解。必须承认,如果计算机不和商业结合的话,很多兼容性引起的问题便不会存在,因此也就不必引入过多的复杂性了,并且,更重要的是,任何技术一开始的时候都是很简单,原理很清晰的,甚至很美观的,正是随着和商业的进一步结合,应用面逐渐变宽,需求也进一步扩展,因此复杂性也就增加了,这些复杂性大多都是在不忍舍弃旧设计所带来的,如果不需要兼容以前的东西,那么完全可以再直接设计一个简单的新系统...最初的ascii码是多么的好,够用,并且刚刚够用,不多也不少,美国人觉得事情已经完成了,可是事情仅仅是在英语国家完成了,在中国,甚至在日本还远远没有完成,大量的中文和假名无法被编码,以至于很多国家为了扎进IT这个大的洪流不得不引入自己的编码规范,于是就到了军阀纷争的阶段,大量的编码规范被提出来。造成这种结果的原因就是美国当年设计ascii码的时候没有把IT当成是全世界的,而只是当成了英语国家的,如果现在再让美国人设计一个编码规范,那么他们肯定不会这么想了,因为他们和中国等国家有大量的生意要做,美国人肯定会设计一种和ascii码同样简单,同样合理,但是能不多不少的融入全世界字符的编码系统,事实上,他们真的这么做了,他们的设计成果就是unicode(虽然unicode组织拥有大量的非美国人,但是大部分还是美国人),可以把现在的unicode比作是全世界的ascii,鉴于ascii是American Standard Code for Information Interchange的缩写,unicode完全可以称作wscii--World-wide Standard Code for Information Interchange,和ascii不同的是,unicode更加抽象了,unicode并不规定传输交换格式,而只是为每一个字符编码了一个数字,是为每个字符而不是每个字形,所以对于简体中文的“户”字和日语中文的“戸”字,合理的办法就是将它们编码到同一个数字,毕竟它们的不同仅仅是书写上的不同,和习惯相关而和字符编码无关,由于unicode是双字节的且不含大小端的信息,因此它不能直接用于交换传输,而必须指定传输编码格式,比如规定一个双字节数字如何编码成单字节流的utf-8编码,以utf-8作为传输编码为例,unicode+utf8一起组成了最终的编码规则,其实是可以直接传输unicode数字的,只要指定大小端即可。
如果全世界都使用了unicode编码那么就不会出现所谓的“中文无法显示”这种问题了,此时的通信应该和计算机工业伊始美国和欧洲使用ascii码通信一样方便快捷,因为大家的编码是一样的,出现这种问题的根源在于通信双方的编码规则不同,这种不同主要原因在于编码规则实在太多了,如果对端使用unicode的utf16编码,传输到本端本端却将之解释成了GBK,那么乱码就几乎是一定的了,除非里面全部是拉丁字符。因此复杂性的根源就是编码规则太多导致需要转码。短时间不可能将所有的编码统一到unicode,因此转码也就是必须的了,毕竟有大量的静态文档都是已经写好的,重新用unicode重写是一件工作量很大的事。编码方案大家都各成一统,很难统一,比如某地a有编码方案A,本地b有编码方案B,a和b通信,在A中,字符“我”被编码成X,而在B中编码为X的字符是“他”,这样在b收到a的消息时,所有的“我”都成了“他”...这就是乱码的根源,即使a使用了unicode,只要b不使用,还是会出现类似问题,因此就出现了很多解决方案,这些解决方案无一不是建立在诸如“内码”,codepage等概念上的。
微软引入codepage的概念,codepage本质上就是unicode和本地编码的一个映射关系,由于unicode是按照抽象字素编码的,为每一个形状的字符分配了一个数字,这些形状由于写法或者文化的不同导致的细微差别则不考虑,因此必然需要有个规则指示它到底代表哪个字符,毕竟unicode只是一个数字而已,这个指示就是本地配置的编码方案,这个方案和font规则一起指示了诸如“户”这个字是简体中文的“户”还是日语中的“戸”,按照unicode的编码规则,它们在unicode中是被编码成同一个数字的(但是实际上并不是这样,二者被编码为了两个数字,不知为何,难道因为日本是发达国家?文中一律将之作为一个编码数字对待)。其实完全可以直接按照unicode的编码数字来显示字符,只要机器上装有unicode的显示规程(TrueType或者点阵)即可,只是那样的话,日语的“戸”也就显示成了简体中文的“户”(unicode不区分字形--一个字符的不同写法或者不同形状,只区分字符)。一般在windows系统中使用codepage来完成unicode和本地编码的映射,本地编码和本地的文化和政策有关系,理想情况下,只需要N个codepage即可,N为所有国家中不同文化地区的总和,每个地区有一个codepage,将unicode编码的字符解释成本地的字形(注意,字形不是字体,字形的区别就是上述“户”和“戸”的区别,写法的不同,而字体则是“宋体”,“黑体”等的区别,写法相同,形象不同),但是实际上并没有那么简单,现实中必须映射诸如A和B之类的本地编码规则到unicode的抽象数字编码,比如字符c在unicode中的编码为uc,在A中的编码为ac,在B中的编码为bc,那么就A和B和unicode映射的两个codepage中分别将有下列映射:
codepageA:
ac c
codepageB
bc c
可以看出,unicode相同的字符c在编码A和编码B中的编码是不同的,codepageA完成了unicode和A的映射。在微软的系统中,codepage的作用非常大,codepage提供两个方向的映射,由于windows系统内核中只处理unicode,那么任何编码在进入内核之前必须转化为unicode,如何转化呢?比如A编码下的字符t如何转化为unicode编码,这就需要查codepage,系统在codepage中查到字符t对应的unicode为u,这样就将u传入更底层参与运算了。反过来,从内核出来的字符编码都是unicode,如何转化为本地的字符编码,也要查codepage,具体使用哪个codepage取决于你想使用哪种编码,通常记事本保存为ansi格式,如果系统要将该文件的字符转为unicode,所依据的就是本地默认的codepage,将此类文件用utraledit或者linux下的hexdump打开看16进制就会看到它们是按照本地默认编码规则来编码的,当然你也可以直接将文件保存为unicode的,此时看16进制的话直接就是字符对应的unicode码。
按照最高内聚最低耦合最大化组合的原则,和编码相关的问题有三个,首先就是抽象编码本身,unicode已经解决了这个问题,它仅仅是抽象数字编码;UTF-X系列解决了编码的传输问题,使得unicode可以选择不同的传输方式,注意,unicode的概念和GBK或者GB2312等并不是并列的,而是处于这些概念的上层,UTF-X才和它们并列;最后一个就是显示问题了,最初的时候,显示是通过点阵文件完成的,系统为每一个字符的编码定义一个点阵,该点阵指示显卡如何显示字符,后来又有了TrueType文件,这些规则标准解决了显示问题。
如果全世界都使用了unicode编码那么就不会出现所谓的“中文无法显示”这种问题了,此时的通信应该和计算机工业伊始美国和欧洲使用ascii码通信一样方便快捷,因为大家的编码是一样的,出现这种问题的根源在于通信双方的编码规则不同,这种不同主要原因在于编码规则实在太多了,如果对端使用unicode的utf16编码,传输到本端本端却将之解释成了GBK,那么乱码就几乎是一定的了,除非里面全部是拉丁字符。因此复杂性的根源就是编码规则太多导致需要转码。短时间不可能将所有的编码统一到unicode,因此转码也就是必须的了,毕竟有大量的静态文档都是已经写好的,重新用unicode重写是一件工作量很大的事。编码方案大家都各成一统,很难统一,比如某地a有编码方案A,本地b有编码方案B,a和b通信,在A中,字符“我”被编码成X,而在B中编码为X的字符是“他”,这样在b收到a的消息时,所有的“我”都成了“他”...这就是乱码的根源,即使a使用了unicode,只要b不使用,还是会出现类似问题,因此就出现了很多解决方案,这些解决方案无一不是建立在诸如“内码”,codepage等概念上的。
微软引入codepage的概念,codepage本质上就是unicode和本地编码的一个映射关系,由于unicode是按照抽象字素编码的,为每一个形状的字符分配了一个数字,这些形状由于写法或者文化的不同导致的细微差别则不考虑,因此必然需要有个规则指示它到底代表哪个字符,毕竟unicode只是一个数字而已,这个指示就是本地配置的编码方案,这个方案和font规则一起指示了诸如“户”这个字是简体中文的“户”还是日语中的“戸”,按照unicode的编码规则,它们在unicode中是被编码成同一个数字的(但是实际上并不是这样,二者被编码为了两个数字,不知为何,难道因为日本是发达国家?文中一律将之作为一个编码数字对待)。其实完全可以直接按照unicode的编码数字来显示字符,只要机器上装有unicode的显示规程(TrueType或者点阵)即可,只是那样的话,日语的“戸”也就显示成了简体中文的“户”(unicode不区分字形--一个字符的不同写法或者不同形状,只区分字符)。一般在windows系统中使用codepage来完成unicode和本地编码的映射,本地编码和本地的文化和政策有关系,理想情况下,只需要N个codepage即可,N为所有国家中不同文化地区的总和,每个地区有一个codepage,将unicode编码的字符解释成本地的字形(注意,字形不是字体,字形的区别就是上述“户”和“戸”的区别,写法的不同,而字体则是“宋体”,“黑体”等的区别,写法相同,形象不同),但是实际上并没有那么简单,现实中必须映射诸如A和B之类的本地编码规则到unicode的抽象数字编码,比如字符c在unicode中的编码为uc,在A中的编码为ac,在B中的编码为bc,那么就A和B和unicode映射的两个codepage中分别将有下列映射:
codepageA:
ac c
codepageB
bc c
可以看出,unicode相同的字符c在编码A和编码B中的编码是不同的,codepageA完成了unicode和A的映射。在微软的系统中,codepage的作用非常大,codepage提供两个方向的映射,由于windows系统内核中只处理unicode,那么任何编码在进入内核之前必须转化为unicode,如何转化呢?比如A编码下的字符t如何转化为unicode编码,这就需要查codepage,系统在codepage中查到字符t对应的unicode为u,这样就将u传入更底层参与运算了。反过来,从内核出来的字符编码都是unicode,如何转化为本地的字符编码,也要查codepage,具体使用哪个codepage取决于你想使用哪种编码,通常记事本保存为ansi格式,如果系统要将该文件的字符转为unicode,所依据的就是本地默认的codepage,将此类文件用utraledit或者linux下的hexdump打开看16进制就会看到它们是按照本地默认编码规则来编码的,当然你也可以直接将文件保存为unicode的,此时看16进制的话直接就是字符对应的unicode码。
按照最高内聚最低耦合最大化组合的原则,和编码相关的问题有三个,首先就是抽象编码本身,unicode已经解决了这个问题,它仅仅是抽象数字编码;UTF-X系列解决了编码的传输问题,使得unicode可以选择不同的传输方式,注意,unicode的概念和GBK或者GB2312等并不是并列的,而是处于这些概念的上层,UTF-X才和它们并列;最后一个就是显示问题了,最初的时候,显示是通过点阵文件完成的,系统为每一个字符的编码定义一个点阵,该点阵指示显卡如何显示字符,后来又有了TrueType文件,这些规则标准解决了显示问题。
总之,总而言之,总结一下,我们之所以遇到很多编码显示的问题,根本原因在于标准的不统一,军阀混战,而且为了向下兼容,必须军阀混战...
本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1271777