【杂谈】Unicode,UTF-8等编码方式的小总结

小记:从广东玩回来寒假也差不多快没了,离开学不久,呆在家里太闲了,稍微看了点CSAPP,第二章的show_bytes和旁注,对Unicode和UTF-8,UTF-16这些东西产生了兴趣,原来还没有彻底搞明白这些东西是什么,看了点别人写的博客加之以实践,略有体会,小小的总结一下。

===============================================以下正文================================================

 

  • Unicode是一种字符集,由2个字节构成,从0000 0000 ~7FFF FFF,每个数字代表一个字符。它不是一种编码方式,而是数字与字符对应的统一表。
  • UTF-16是对Unicode的直接实现,根据Unicode对每个字符的编码来存储字符,大部分由2个字节构成,超过2个字节用4个字节构成,不兼容ASCII码,它受到大端小端法的影响。
  • UTF-8是对Unicode不同方式的实现,利用自己的规则进行编码,优点是使得128个常用字符可以只用1个字节来储存,缺点是存储其他字符需要用到2-6个字节。

 

因为UTF-16是对Unicode的直接实现,所以对其编码方式没什么好说的,百度百科UTF-8中的一张表吸引了我的兴趣:

Unicode bit数 UTF8 byte数
0000 0000 ~
0000 007F
0~7 0XXX XXXX 1
0000 0080 ~
0000 07FF
8~11
110X XXXX
10XX XXXX
2
0000 0800 ~
0000 FFFF
12~16
1110 XXXX
10XX XXXX
10XX XXXX
3
0001 0000 ~
001F FFFF
17~21
1111 0XXX
10XX XXXX
10XX XXXX
10XX XXXX
4
0020 0000 ~
03FF FFFF
22~26
1111 10XX
10XX XXXX
10XX XXXX
10XX XXXX
10XX XXXX
5
0400 0000 ~
7FFF FFFF
27~31
1111 110X
10XX XXXX
10XX XXXX
10XX XXXX
10XX XXXX
10XX XXXX
6

UTF-8的编码很巧妙,可以看到,在Unicode值在0000 007F之前UTF-8都和Unicode的第二个数字一样,它只用了1个字节,而这128个字符是最常用的控制符和拉丁文字,相比于UTF-16用2个字节编码,在全英文的状况下是大大节省了空间,http://baike.baidu.com/view/40801.htm可以看到Unicode对不同文字所用的区域。

当超出128个字符时,UTF-8利用2个字节编码,但是,用UTF-8规则读取一段内存的时候如何知道它是用1个字节还是多个字节编码的呢?UTF-8的解决办法是在首字节的开头位用1来标示对于这一个字符需要读取几个字节,如上图所示。当读取到1110 XXXX这个信息后,就知道包括这个字节在内的接下来3个字节包含了一个字符的信息。这种办法的优点在于可以将最常用的字符用1个字节储存减少空间占用,取而代之的其他字符就需要用更多的字节来编码,UTF-16比UTF-8多利用的就是UTF-8前面的标示读取几个字节的位,所谓有得必有失。

 

利用CSAPP书上的一个例子,可以简单的查看UTF-8的具体编码。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef unsigned char *byte_pointer;

void show_bytes(byte_pointer start, int len)
{
    int i;
    for (i = 0; i < len; i++)
    printf(" %.2x", start[i]);
    printf("\n");
}

int main()
{
    const char* s1 = "我我是是超超威威蓝蓝猫猫猫猫";
    const char* s2 = "aabbAABB";
    show_bytes ( (byte_pointer)s1,strlen(s1)+1);
    printf("\n\n");
    show_bytes ( (byte_pointer)s2,strlen(s2)+1);
    system("pause");
    return 0;
}

输出结果是:

e6 88 91 e6 88 91 e6 98 af e6 98 af e8 b6 85 e8 b6 85 e5 a8 81 e5 a8 81 e8 93 9d e8 93 9d e7 8c ab e7 8c ab e7 8c ab e7 8c ab 00


61 61 62 62 41 41 42 42 00

可以看出来“我是超威蓝猫”这几个汉字是用3个字节编码的,而abAB是用2个字节编码的。记得很早以前貌似是小学的计算机课就学过汉字占2个字节,那是在GB编码下的,GB编码专门用于汉字的编码并且兼容ASCII,相比于UTF-8的3个字节的汉字,GB显然减少了空间占用。

 

 

posted @ 2013-02-16 21:46  Azard  阅读(355)  评论(1编辑  收藏  举报