【转】字符编码简介

原文网址:http://blog.csdn.net/trochiluses/article/details/8782019

1.问题:乱码

     在linux上,经常遇到这样的问题:新安转过的系统,经常无法显示汉字(乱码);使用Vim或者gedit等编辑器的时候经常把汉字显示位乱码。使用python等语言来处理网页文件,经常会出现乱码的情况。所有的这些问题都和字符编码有关

2.为何会出现乱码?

    计算机中储存的信息都是用二进制数表示的;而我们在屏幕上看到的英文、汉字等字符是二进制数转换之后的结果。通俗的说,按照何种规则将字符存储在计算机中。例如ASCII采用7位编码,a被编号为65,所有字符编码最高位都为0;此时如果计算机读取到某字节是是65,就显示“a”;如果某个字节存储的是ox1000,0000,而我们仍然采用ASCII进行解码,此时就会无法解码或者出现乱码。这就是说,编码要于解码对应才不会出现乱码。

3.常用字符编码

    常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、GB18030字符集、Unicode字符集等。计算机要准确的处理各种字符集文字,需要进行字符编码,以便计算机能够识别和存储各种文字。 

3.1 ASCII编码

    美国信息交换标准代码是一种用于信息交换的美国标准代码。7位字符集广泛用于代表标准美国键盘上的字符或符号。通过将这些字符使用的值标准化,ASCII允许计算机和计算机程序交换信息。ASCII字符集是与ANSI字符集中的前面128个(0-127)字符相同。

    编码内容:常用英文字符/控制字符。

    字符集数量:128

    编码特征:每个编码长度均为一个字节,高位是0

    优缺点:字符集数量过小,对欧洲常用字符支持比较弱。

    为了解决字符集数量太少的问题,衍生出EASCII字符集,仍然是一个字节,但是高位为1.

3.2 GB2312编码

    为了解决汉字编码问题,GB2312规定:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(他称之为高字节)从0xA1用到 0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了。在这些编码里,还把数学符号、罗马希腊的 字母、日文的假名们都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。

    特点:2字节编码,最高位都为1(如果为0,将按照ASCII解码)

    评介:解决了汉字编码问题,但是简体字与生僻字的问题没有解决。

3.3 GB18030编码

    简介:GB 18030,全称:国家标准GB 18030-2005《信息技术 中文编码字符集》,是中华人民共和国现时最新的内码字集。

    特点:

  • UTF-8相同,采用多字节编码,每个字可以由1个、2个或4个字节组成。
  • 编码空间庞大,最多可定义161万个字符。
  • 支持中国国内少数民族的文字,不需要动用造字区。
  • 汉字收录范围包含繁体汉字以及日韩汉字

3.4 BIG5字符集

      Big5,又称为大五码或五大码,是使用繁体中文(正体中文)社区中最常用的电脑汉字字符集标准,共收录13,060个汉字。中文码分为内码交换码两类,Big5属中文内码,知名的中文交换码有CCCIICNS11643。Big5虽普及于台湾香港澳门等繁体中文通行区,但长期以来并非当地的国家标准,而只是业界标准倚天中文系统Windows等主要系统的字符集都是以Big5为基准,但厂商又各自增加不同的造字与造字区,派生成多种不同版本。2003年,Big5被收录到CNS11643中文标准交换码的附录当中,取得了较正式的地位。这个最新版本被称为Big5-2003。

4.UNIcode

    为了适合当地语言和字符,设计和实现类似GB2312/GBK/GB18030/BIG5的编码方案。这样各搞一套,在本地使用没有问题,一旦出现在网络中,由于不兼容,互相访问就出现了乱码现象。

   举个例子:

   在西方国家的EASCII之中,如果一个8b的数字用来表示一个字符,当最高位是1的时候,它表示一个拉丁字符等其他特殊字符;但是中文编码GB2312却规定,两个8b的字符,如果高位为1,那么它表示一个汉子。具体而言,“1111,0111;1111,0111”使用EASCII表示两个约等号,使用GB2312解码却表示一个汉子:也就是说,同样的存储,用不同的编码方案来解码,得到的结果不同。另外一个方面,同样对于“约等于号”,GB2312给它的编码是A1D006:对于同样的字符,不同的字符集有不同的编码。

 

    为了解决这个问题,一个伟大的创想产生了——Unicode。Unicode编码系统为表达任意语言的任意字符而设计。可以想象,如果有一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,那么乱码问题就会消失。这就是Unicode,就像它的名字都表示的,这是一种所有符号的编码。它使用4字节的数字来表达每个字母、符号,或者表意文字(ideograph)。每个数字代表唯一的至少在某种语言中使用的符号。(并不是所有的数字都用上了,但是总数已经超过了65535,所以2个字节的数字是不够用的。)被几种语言共用的字符通常使用相同的数字来编码,除非存在一个在理的语源学(etymological)理由使不这样做。不考虑这种情况的话,每个字符对应一个数字,每个数字对应一个字符。即不存在二义性。不再需要记录"模式"了。U+0041总是代表'A',即使这种语言没有'A'这个字符。

Unicode是字符集,UTF-32/ UTF-16/ UTF-8是三种字符编码方案。

 

Unicode当然是一个很大的集合,现在的规模可以容纳100多万个符号。每个符号的编码都不一样,比如,U+0639表示阿拉伯字母Ain,U+0041表示英语的大写字母A,U+4E25表示汉字"严"。

 

5.UNICODE的问题

 

需要注意的是,Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。

比如,汉字"严"的unicode是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。

这里就有两个严重的问题,第一个问题是,如何才能区别Unicode和ASCII?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果Unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。

它们造成的结果是:1)出现了Unicode的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示Unicode。2)Unicode在很长一段时间内无法推广,直到互联网的出现。

 

5.UTF-8

 

UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码定长码),也是一种前缀码。它可以用来表示Unicode标准中的任何字符,且其编码中的第一个字节仍与ASCII兼容,这使得原来处理ASCII字符的软件无须或只须做少部份修改,即可继续使用。因此,它逐渐成为电子邮件网页及其他存储或传送文字的应用中,优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。

 

下表总结了编码规则,字母x表示可用编码的位。

Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

跟据上表,解读UTF-8编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。

下面,还是以汉字"严"为例,演示如何实现UTF-8编码。

已知"严"的unicode是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800-0000 FFFF),因此"严"的UTF-8编码需要三个字节,即格式是"1110xxxx 10xxxxxx 10xxxxxx"。然后,从"严"的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,"严"的UTF-8编码是"11100100 10111000 10100101",转换成十六进制就是E4B8A5。

 

 

 

参考文献:

1.吴秦 “unicode的创想”:http://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html

2.阮一峰  “字符编码笔记:ASCII,Unicode 和UTF-8”:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

posted on 2015-01-21 10:54  wi100sh  阅读(301)  评论(0编辑  收藏  举报

导航