• [转]ASCII,ANSI,UNICODE,UTF8,UNICOD BIG Endian 等字符编码问题


    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


  • 相关阅读:
    Linux:修改Shell命令提示符及颜色
    Linux:cut命令详解
    pageadmin去掉xxx
    高手详解SQL性能优化十条经验
    一道简单递归题
    list<?>转换成 对应的 class
    《一道笔试题》找出最连续数字的最大长度
    poi 获取excel数据 导入数据库
    有一个5ml 的瓶子 和3ml 的瓶子 和 很多水 现在 要取出4ml的水 请写出编程 多种解法
    假设字符串类似这样的aba和aab,abc和bca就相等,现在随便给你二组字符串,请编程比较他们看是否相等
  • 原文地址:https://www.cnblogs.com/lauer0246/p/1383052.html
Copyright © 2020-2023  润新知