现在的位置: 首页 > 综合 > 正文

[转]ASCII,ANSI,UNICODE,UTF-8,UNICOD BIG Endian 等字符编码问题

2012年11月22日 ⁄ 综合 ⁄ 共 9814字 ⁄ 字号 评论关闭

http://topic.csdn.net/t/20060706/10/4863472.html

  字符集简史:  

          在所有字符集中,最知名可能要数被称为ASCII的7位字符集了。它是美国信息交换标准委员会(American   Standards   Committee   for   Information   Interchange)的缩写,   为美国英语通信所设计。它由128个字符组成,包括大小写字母、数字0-9、标点符号、非打印字符(换行符、制表符等4个)以及控制字符(退格、响铃等) 组成。    
   
          但是,由于他是针对英语设计的,当处理带有音调标号(形如汉语的拼音)的欧洲文字时就会出现问题。因此,创建出了一些包括255个字符的由ASCII扩展 的字符集。其中有一种通常被成为IBM字符集,它把值为128-255之间的字符用于画图和画线,以及一些特殊的欧洲字符。另一种8位字符集是ISO   8859-1   Latin   1,也简称为ISO   Latin-1。它把位于128-255之间的字符用于拉丁字母表中特殊语言字符的编码,也因此而得名。    
   
          欧洲语言不是地球上的唯一语言,因此亚洲和非洲语言并不能被8位字符集所支持。仅汉语(或pictograms)字母表就有80000以上个字符。但是把 汉语、日语和越南语的一些相似的字符结合起来,在不同的语言里,使不同的字符代表不同的字,这样只用2个字节就可以编码地球上几乎所有地区的文字。因此, 创建了UNICODE编码。它通过增加一个高字节对ISO   Latin-1字符集进行扩展,当这些高字节位为0时,低字节就是ISO   Latin-1字符。UNICODE支持欧洲、非洲、中东、亚洲(包括统一标准的东亚像形汉字和韩国像形文字)。但是,UNICODE并没有提供对诸如 Braille,   Cherokee,   Ethiopic,   Khmer,   Mongolian,   Hmong,   Tai   Lu,   Tai   Mau文字的支持。同时它也不支持如Ahom,   Akkadian,   Aramaic,   Babylonian   Cuneiform,   Balti,   Brahmi,   Etruscan,   Hittite,   Javanese,   Numidian,   Old   Persian   Cuneiform,   Syrian之类的古老的文字。    
   
          事实证明,对可以用ASCII表示的字符使用UNICODE并不高效,因为UNICODE比ASCII占用大一倍的空间,而对ASCII来说高字节的0对 他毫无用处。为了解决这个问题,就出现了一些中间格式的字符集,他们被称为通用转换格式,既UTF(Universal   Transformation   Format)。目前存在的UTF格式有:UTF-7,   UTF-7.5,   UTF-8,   UTF-16,   以及   UTF-32。本文讨论UTF-8字符集的基础。    
   
  UTF-8字符集  
   
          UTF意为通用字集转换格式(Universal   Character   Set   Transformation   Format),UTF这是为传输而设计的编码,UTF-8是Unicode的8位元格式。   UTF-8是UNICODE的一种变长字符编码,由Ken   Thompson于1992年创建。现在已经标准化为RFC   3629。UTF-8用1到6个字节编码UNICODE字符。如果UNICODE字符由2个字节表示,则编码成UTF-8很可能需要3个字节,而如果 UNICODE字符由4个字节表示,则编码成UTF-8可能需要6个字节。用4个或6个字节去编码一个UNICODE字符可能太多了,但很少会遇到那样的 UNICODE字符。    
   
  UFT-8转换表表示如下:    
   
          UNICODE编码(16进制)             UTF-8字节流(二进制)    
          0x00000000   -   0x0000007F         0xxxxxxx    
          0x00000080   -   0x000007FF         110xxxxx   10xxxxxx    
          0x00000800   -   0x0000FFFF         1110xxxx   10xxxxxx   10xxxxxx    
          0x00010000   -   0x001FFFFF         11110xxx   10xxxxxx   10xxxxxx   10xxxxxx    
          0x00200000   -   0x03FFFFFF         111110xx   10xxxxxx   10xxxxxx   10xxxxxx   10xxxxxx    
          0x04000000   -   0x7FFFFFFF         1111110x   10xxxxxx   10xxxxxx   10xxxxxx   10xxxxxx   10xxxxxx    
   
          实际表示ASCII字符的UNICODE字符,将会编码成1个字节,并且UTF-8表示与ASCII字符表示是一样的。所有其他的UNCODE字符转化成 UTF-8将需要至少2个字节。每个字节由一个换码序列开始。第一个字节由唯一的换码序列,由n位1加一位0组成。n位1表示字符编码所需的字节数。    
   
  示例:  
          UNICODE的:"CA"(11001010)   编码成UTF-8将需要2个字节:   CA   ->   C3   8A  
          UNICODE的:"F03F"   (11110000   00111111)   编码成UTF-8将需要3个字节:F03F   ->   EF   80   BF  
   
          译者注:由上分析可以看到,UNCODE到UTF-8的转换就是先把UNCODE的字符转换成二进制,再由低到高六位六位额的取,每取一个六位在着六位的 前面加上10,就构成一个八位。知道取到最后剩余的高位补1。(但是如果UNCODE转换的二进制小于等于01111111,那么UTF-8就是这个编 码,保持不变。)(本人修改)。    
   
  UTF-8编码的优点:    
          UTF-8编码可以通过屏蔽位和移位操作快速读写。字符串比较时strcmp()和wcscmp()的返回结果相同,因此使排序变得更加容易。字节FF和 FE在UTF-8编码中永远不会出现,因此他们可以用来表明UTF-16或UTF-32文本(见BOM)   UTF-8   是字节顺序无关的。它的字节顺序在所有系统中都是一样的,因此它实际上并不需要BOM。    
   
  UTF-8编码的缺点:    
          你无法从UNICODE字符数判断出UTF-8文本的字节数,因为UTF-8是一种变长编码它需要用2个字节编码那些用扩展ASCII字符集只需1个字节 的字符   ISO   Latin-1   是UNICODE的子集,但不是UTF-8的子集   8位字符的UTF-8编码会被email网关过滤,因为internet信息最初设计为7为ASCII码。因此产生了UTF-7编码。   UTF-8   在它的表示中使用值100xxxxx的几率超过50%,   而现存的实现如ISO   2022,   4873,   6429,   和8859系统,会把它错认为是C1   控制码。因此产生了UTF-7.5编码。    
   
  修正的UTF-8:    
          java使用UTF-16表示内部文本,并支持用于字符串串行化的非标准的修正UTF-8编码。标准UTF-8和修正的UTF-8有两点不同:修正的 UTF-8中,null字符编码成2个字节(11000000   00000000)   而不是标准的1个字节(00000000),这样作可以保证编码后的字符串中不会嵌入null字符。因此如果在类C语言中处理字符串,文本不会在第一个 null字符时截断(C字符串以null结尾)。在标准UTF-8编码中,超出基本多语言范围(BMP   -   Basic   Multilingual   Plain)的字符被编码为4字节格式,但是在修正的UTF-8编码中,他们由代理编码对(surrogate   pairs)表示,然后这些代理编码对在序列中分别重新编码。结果标准UTF-8编码中需要4个字节的字符,在修正后的UTF-8编码中将需要6个字节。    
   
  位序标志BOM:  
          BOM(Byte   Order   Mark)是一个字符,它表明UNICODE文本的UTF-16,UTF-32的编码字节顺序(高字节低字节顺序)和编码方式(UTF-8,UTF- 16,UTF-32,   其中UTF-8编码是字节顺序无关的)。    
   
          Encoding       Representation    
          UTF-8             EF   BB   BF    
          UTF-16           Big   Endian   FE   FF    
          UTF-16           Little   Endian   FF   FE    
          UTF-32           Big   Endian   00   00   FE   FF    

          UTF-32           Little   Endian   FF   FE   00   00

UTF-8   C++   Encoding   Sample  
          一下四个函数用C++实现了2个和4个字节的UNICODE<-->UTF-8的编码解码过程。  
   
   
  #define                   MASKBITS                                 0x3F  
  #define                   MASKBYTE                                 0x80  
  #define                   MASK2BYTES                             0xC0  
  #define                   MASK3BYTES                             0xE0  
  #define                   MASK4BYTES                             0xF0  
  #define                   MASK5BYTES                             0xF8  
  #define                   MASK6BYTES                             0xFC  
   
  typedef   unsigned   short       Unicode2Bytes;  
  typedef   unsigned   int           Unicode4Bytes;  
   
  void   UTF8Encode2BytesUnicode(std::vector<   Unicode2Bytes   >   input,  
                                                            std::vector<   byte   >&   output)  
  {  
        for(int   i=0;   i   <   input.size();   i++)  
        {  
              //   0xxxxxxx  
              if(input[i]   <   0x80)  
              {  
                    output.push_back((byte)input[i]);  
              }  
              //   110xxxxx   10xxxxxx  
              else   if(input[i]   <   0x800)  
              {  
                    output.push_back((byte)(MASK2BYTES   |   input[i]   >>   6));  
                    output.push_back((byte)(MASKBYTE   |   input[i]   &   MASKBITS));  
              }  
              //   1110xxxx   10xxxxxx   10xxxxxx  
              else   if(input[i]   <   0x10000)  
              {  
                    output.push_back((byte)(MASK3BYTES   |   input[i]   >>   12));  
                    output.push_back((byte)(MASKBYTE   |   input[i]   >>   6   &   MASKBITS));  
                    output.push_back((byte)(MASKBYTE   |   input[i]   &   MASKBITS));  
              }  
        }  
  }  
   
  void   UTF8Decode2BytesUnicode(std::vector<   byte   >   input,  
                                                            std::vector<   Unicode2Bytes   >&   output)  
  {  
        for(int   i=0;   i   <   input.size();)  
        {  
              Unicode2Bytes   ch;  
   
              //   1110xxxx   10xxxxxx   10xxxxxx  
              if((input[i]   &   MASK3BYTES)   ==   MASK3BYTES)  
              {  
                    ch   =   ((input[i]   &   0x0F)   <<   12)   |   (  
                                (input[i+1]   &   MASKBITS)   <<   6)  
                              |   (input[i+2]   &   MASKBITS);  
                    i   +=   3;  
              }  
              //   110xxxxx   10xxxxxx  
              else   if((input[i]   &   MASK2BYTES)   ==   MASK2BYTES)  
              {  
                    ch   =   ((input[i]   &   0x1F)   <<   6)   |   (input[i+1]   &   MASKBITS);  
                    i   +=   2;  
              }  
              //   0xxxxxxx  
              else   if(input[i]   <   MASKBYTE)  
              {  
                    ch   =   input[i];  
                    i   +=   1;  
              }  
   
              output.push_back(ch);  
        }  
  }  
   
  void   UTF8Encode4BytesUnicode(std::vector<   Unicode4Bytes   >   input,  
                                                            std::vector<   byte   >&   output)  
  {  
        for(int   i=0;   i   <   input.size();   i++)  
        {  
              //   0xxxxxxx  
              if(input[i]   <   0x80)  
              {  
                    output.push_back((byte)input[i]);  
              }  
              //   110xxxxx   10xxxxxx  
              else   if(input[i]   <   0x800)  
              {  
                    output.push_back((byte)(MASK2BYTES   |   input[i]   >   6));  
                    output.push_back((byte)(MASKBYTE   |   input[i]   &   MASKBITS));  
              }  
              //   1110xxxx   10xxxxxx   10xxxxxx  
              else   if(input[i]   <   0x10000)  
              {  
                    output.push_back((byte)(MASK3BYTES   |   input[i]   >>   12));  
                    output.push_back((byte)(MASKBYTE   |   input[i]   >>   6   &   MASKBITS));  
                    output.push_back((byte)(MASKBYTE   |   input[i]   &   MASKBITS));  
              }  
              //   11110xxx   10xxxxxx   10xxxxxx   10xxxxxx  
              else   if(input[i]   <   0x200000)  
              {  
                    output.push_back((byte)(MASK4BYTES   |   input[i]   >>   18));  
                    output.push_back((byte)(MASKBYTE   |   input[i]   >>   12   &   MASKBITS));  
                    output.push_back((byte)(MASKBYTE   |   input[i]   >>   6   &   MASKBITS));  
                    output.push_back((byte)(MASKBYTE   |   input[i]   &   MASKBITS));  
              }  
              //   111110xx   10xxxxxx   10xxxxxx   10xxxxxx   10xxxxxx  
              else   if(input[i]   <   0x4000000)  
              {  
                    output.push_back((byte)(MASK5BYTES   |   input[i]   >>   24));  
                    output.push_back((byte)(MASKBYTE   |   input[i]   >>   18   &   MASKBITS));  
                    output.push_back((byte)(MASKBYTE   |   input[i]   >>   12   &   MASKBITS));  
                    output.push_back((byte)(MASKBYTE   |   input[i]   >>   6   &   MASKBITS));  
                    output.push_back((byte)(MASKBYTE   |   input[i]   &   MASKBITS));  
              }  
              //   1111110x   10xxxxxx   10xxxxxx   10xxxxxx   10xxxxxx   10xxxxxx  
              else   if(input[i]   <   0x8000000)  
              {  
                    output.push_back((byte)(MASK6BYTES   |   input[i]   >>   30));  
                    output.push_back((byte)(MASKBYTE   |   input[i]   >>   18   &   MASKBITS));  
                    output.push_back((byte)(MASKBYTE   |   input[i]   >>   12   &   MASKBITS));  
                    output.push_back((byte)(MASKBYTE   |   input[i]   >>   6   &   MASKBITS));  
                    output.push_back((byte)(MASKBYTE   |   input[i]   &   MASKBITS));  
              }  
        }  
  }  
   
  void   UTF8Decode4BytesUnicode(std::vector<   byte   >   input,  
                                                            std::vector<   Unicode4Bytes   >&   output)  
  {  
        for(int   i=0;   i   <   input.size();)  
        {  
              Unicode4Bytes   ch;  
   
              //   1111110x   10xxxxxx   10xxxxxx   10xxxxxx   10xxxxxx   10xxxxxx  
              if((input[i]   &   MASK6BYTES)   ==   MASK6BYTES)  
              {  
                    ch   =   ((input[i]   &   0x01)   <<   30)   |   ((input[i+1]   &   MASKBITS)   <<   24)  
                              |   ((input[i+2]   &   MASKBITS)   <<   18)   |   ((input[i+3]  
                                                  &   MASKBITS)   <<   12)  
                              |   ((input[i+4]   &   MASKBITS)   <<   6)   |   (input[i+5]   &   MASKBITS);  
                    i   +=   6;  
              }  
              //   111110xx   10xxxxxx   10xxxxxx   10xxxxxx   10xxxxxx  
              else   if((input[i]   &   MASK5BYTES)   ==   MASK5BYTES)  
              {  
                    ch   =   ((input[i]   &   0x03)   <<   24)   |   ((input[i+1]  
                                  &   MASKBITS)   <<   18)  
                              |   ((input[i+2]   &   MASKBITS)   <<   12)   |   ((input[i+3]  
                                      &   MASKBITS)   <<   6)  
                              |   (input[i+4]   &   MASKBITS);  
                    i   +=   5;  
              }  
              //   11110xxx   10xxxxxx   10xxxxxx   10xxxxxx  
              else   if((input[i]   &   MASK4BYTES)   ==   MASK4BYTES)  
              {  
                    ch   =   ((input[i]   &   0x07)   <<   18)   |   ((input[i+1]  
                                  &   MASKBITS)   <<   12)  
                              |   ((input[i+2]   &   MASKBITS)   <<   6)   |   (input[i+3]   &   MASKBITS);  
                    i   +=   4;  
              }  
              //   1110xxxx   10xxxxxx   10xxxxxx  
              else   if((input[i]   &   MASK3BYTES)   ==   MASK3BYTES)  
              {  
                    ch   =   ((input[i]   &   0x0F)   <<   12)   |   ((input[i+1]   &   MASKBITS)   <<   6)  
                              |   (input[i+2]   &   MASKBITS);  
                    i   +=   3;  
              }  
              //   110xxxxx   10xxxxxx  
              else   if((input[i]   &   MASK2BYTES)   ==   MASK2BYTES)  
              {  
                    ch   =   ((input[i]   &   0x1F)   <<   6)   |   (input[i+1]   &   MASKBITS);  
                    i   +=   2;  
              }  
              //   0xxxxxxx  
              else   if(input[i]   <   MASKBYTE)  
              {  
                    ch   =   input[i];  
                    i   +=   1;  
              }  
              output.push_back(ch);  
        }  
  }  

  

相关博文:http://www.cnblogs.com/silence516/archive/2008/11/03/1325646.html

抱歉!评论已关闭.