用C语言实现UCS-2和UTF-8之间的互相转化

类别:编程语言 点击:0 评论:0 推荐:


本文简单介绍UCS,UNICODE和UTF-8,并利用C语言实现了UTF-8与UCS2之间的互相转化。
1.什么是UCS和ISO10646?
国际标准ISO10646定义了通用字符集(Universal Character Set, UCS). UCS是所有其它字符集标准的一个超集,它保证也其它字符集双向兼容,即编码间相互转换不会丢失任何信息。UCS字符集U+0000到U+007F与US-ASCII是一致的。

2.什么是UNICODE
历史上, 有两个独立的, 创立单一字符集的尝试. 一个是国际标准化组织(ISO)的 ISO 10646 项目, 另一个是由(一开始大多是美国的)多语言软件制造商组成的协会组织的 Unicode 项目. 幸运的是, 1991年前后, 两个项目的参与者都认识到, 世界不需要两个不同的单一字符集. 它们合并双方的工作成果, 并为创立一个单一编码表而协同工作. 两个项目仍都存在并独立地公布各自的标准, 但 Unicode 协会和 ISO/IEC JTC1/SC2 都同意保持 Unicode 和 ISO 10646 标准的码表兼容, 并紧密地共同调整任何未来的扩展.

3.什么是UTF-8(一种传送和存储格式)
UCS和UNICODE为每个字符分配了一个对应的整数,但并没有明确说明其实现机制.故存在多种编码方式,其中以两个字节和四个字节来存储一个字符的方法分别叫UCS-2, UCS-4,要将一个ASCII文件转换成一个UCS-2文件只要在每个字节前加一个字节0X00,转换成UCS-4只要在每个字节前加三个0X00。
而internet上大量的信息是以ASCII码存在的,如果都用两个字节来存储将浪费大量的资源,同时Unix和Linux下使用USC-2和USC-4会导致严重问题,于是出现了UTF-8(定义于ISO10646-1).
UTF-8(UTF-8 stands for Unicode Transformation Format-8. It is an octet (8-bit) lossless encoding of Unicode characters.)

UNICODE(UCS)和UTF-8的对应关系。
U-00000000 - U-0000007F:  0xxxxxxx 
U-00000080 - U-000007FF:  110xxxxx 10xxxxxx 
U-00000800 - U-0000FFFF:  1110xxxx 10xxxxxx 10xxxxxx 
U-00010000 - U-001FFFFF:  11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 
U-00200000 - U-03FFFFFF:  111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 
U-04000000 - U-7FFFFFFF:  1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

在多字节串中,第一个字节的开头‘1’的数目就是整个串中字节的数目.

下面举UCS-2与UTF-8的对应关系,并利用C语言实现之间的互相转化。
-----------------------------------------------------------------------------------------------------------
| UCS2                       | UTF-8                             |
|----------------------------------------------------------------------------------------------------------
|                               |    code        | 1st Byte     | 2nd byte | 3rd Byte   |
|--------------------------------------------------------------------------------------------------------
| 000000000aaaaaaa    | 0000 - 007F | 0aaaaaaa   |               |                |
|--------------------------------------------------------------------------------------------------------
| 00000bbbbbaaaaaa   | 0080 - 07FF  | 110bbbbb | 10aaaaaa  |                |
|--------------------------------------------------------------------------------------------------------
| ccccbbbbbbaaaaaa    | 0800 - FFFF  | 1110cccc  | 10bbbbbb | 10aaaaaa   |
|--------------------------------------------------------------------------------------------------------

在这儿我只实现了单个字符的转换,串的转换也是一样的道理。
1,把一个UTF-8字符转换成一个UCS-2字符。
如果转换成功返回1,如果UTF-8字符是一个unrecognized字符,则返回0,且存一个blackbox(U+22e0)到ucs2_code_ptr中。


typedef unsigned short UINT16;
typedef unsigned char UINT8;
typedef unsigned char BOOL;
#define TRURE (BOOL)(1)
#define FALSE (BOOL)(0)

BOOL UTF8toUCS2Code(const UINT8* utf8_code, UINT16* ucs2_code){
       UINT16 temp1, temp2;
       BOOL is_unrecognized = FALSE ;
       UINT16 * in = utf8_code;
       if(!utf8_code || !ucs2_code){
             return is_unrecognized;
      }
     
      if(0x00 == (*in & 0x80)){
      /* 1 byte UTF-8 Charater.*/
             *ucs2_code= (UINT16)*in;
             is_unrecognized = TRUE;
      }
      else if(0xc0 == (*in & 0xe0) &&
               0x80 == (*(in + 1) & 0xc0)
              ){
      /* 2 bytes UTF-8 Charater.*/ 
             temp1 = (UINT16)(*in & 0x1f);
             temp1 <<= 6;
             temp1 |= (UINT16)(*(in + 1) & 0x3f);
             *ucs2_code = temp1;
             is_unrecognized = TRUE;
      }
      else if( 0xe0 == (*in & 0xf0) &&
                0x80 == (*(in +1) & 0xc0) &&
                0x80 == (*(in + 2) & 0xc0)
              ){
      /* 3bytes UTF-8 Charater.*/
             temp1 = (UINT16)(*in &0x0f);
             temp1 <<= 12;
             temp2 = (UINT16)(*(in+1) & 0x3F);
             temp2 <<= 6;
             temp1 = temp1 | temp2 | (UINT16)(*(in+2) & 0x3F);
             *ucs2_code = temp1;
             is_unrecognized  = TRUE;
       }
       else{
       /* unrecognize byte. */
             *ucs2_code = 0x22e0;
             is_unrecognized = FALSE;
     }
     return is_unrecognized;
}

2,把一个UCS-2字符转换成UTF-8字符。函数返回转换成UTF-8的长度(字节1 -- 3),如果目标指针为空,返回0。

UINT8 UCS2toUTF8Code(UINT16 ucs2_code, UINT8* utf8_code){
      int length = 0;
      UINT8* out = utf8_code;
      if(!utf8_code){
           return length;
      }
      if(0x0080 > ucs2_code){
      /* 1 byte UTF-8 Character.*/
          *out = (UINT8)ucs2_code;
          length++;  
      }
      else if(0x0800 > ucs2_code){
      /*2 bytes UTF-8 Character.*/
           *out = ((UINT8)(ucs2_code >> 6)) | 0xc0;
           *(out+1) = ((UINT8)(ucs2_code & 0x003F)) | 0x80;
           length += 2;
     }
     else{
     /* 3 bytes UTF-8 Character .*/
        *out = ((UINT8)(ucs2_code >> 12)) | 0xE0;
        *(out+1) = ((UINT8)((ucs2_code & 0x0FC0)>> 6)) | 0x80;
        *(out+2) = ((UINT8)(ucs2_code & 0x003F)) | 0x80;
        length += 3;              
    }
    return length;
}

字符串间的转换也是一样的。

本文地址:http://com.8s8s.com/it/it28915.htm