字符编码 ASCII UTF-8 UNICODE 的关系

来源:互联网 发布:怎么淘宝刷単赚钱 编辑:程序博客网 时间:2024/05/19 16:37

豁然开朗,终于理顺了Unicode、utf-8等之间的关系,一直都是糊里糊涂的,知道今天看到了下面这篇文章!

http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

弄计算机这一行,就必须懂得一点字符编码的知识。

ASCII码

一个字节有8个二进制位,对应256种状态,每种状态对应一个符号,就有256个符号。从0000 0000到1111 1111.

ASCII码,一共规定了128个字符,如A为65等等。这128个字符,只占用了一个字节的后7位,所以第一位就为0了。

对于英语,用128个符号编码就足够了

非ASCII编码

     对于其他语言,128个符号是不够的。有的语言可以利用128~255这一段,如法语,希伯来语等。但是这样又会带来新的问题。虽然都是使用256个符号的编码方式,但不同的国家有不同的字母。

     更别说亚洲国家的文字,要求的符号就更多了,其中汉字就达10万之多。一个字节肯定是不够的,就必须用多个字节才能表示一个符号。比如,常见的中文编码GB2312。使用两个字节表示一个汉字,理论上可以表示256*256个汉字。

     正因为得多个字节表示一个符号,才有了Unicode。

Unicode

     Unicode是一个符号集,可以将世界上所有的符号容纳其中。每个符号给予一个独一无二的编码,那么就可以解决乱码问题。如U+4E25代表汉字‘严’。

注意:Unicode只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储(见番外_大端与小端)。

 

     但是Unicode会带来问题,啥问题呢?比如英文字符只要一个字符,汉字‘严’,4E25,这个符号要两个字符;还有更大的字符,需要三个字符甚至4个字符。问题就是这些字符怎么区分到底是几个字节呢?

另外,若是统一存放字节数。即每个字符均用相同的字符数,方便是方便,但这对存储会造成极大的浪费。比如,本来一个字符的,硬要存3个或4个字符,文件就会比原来大小大二三倍。这显然是无法接受的。

UTF-8

everything is gonna be fine。

UTF-8就是Unicode的一种实现方式。其他实现方式UTF-16(2或4字节)和UTF-32(4字节)


<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">UTF-8是一种变长的编码方式。可以使用1~4个字节来表示一个符号,适应性很强,是互联网使用最强的编码方式。</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">下面是UTF-8的编码规则:</span>

Unicode编码(十六进制)

UTF-8 字节流(二进制)

000000 - 00007F

0xxxxxxx

000080 - 0007FF

110xxxxx 10xxxxxx

000800 - 00FFFF

1110xxxx 10xxxxxx 10xxxxxx

010000 - 10FFFF

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

还是拿汉字严为例:4E25(01001110 00100101),属于(000800~00FFFF)段,因此‘严’编码需要三个字节,即1110010010111000 10100101,转成16进制是E4B8A5。

UTF-16

因为这个字超过U+FFFF所以无法用UCS-2的格式编码

16进制编码范围

UTF-16表示方法(二进制)

10进制码范围

字节数量

U+0000---U+FFFF

xxxxxxxx xxxxxxxx yyyyyyyy yyyyyyyy

0-65535

2

U+10000---U+10FFFF

110110yyyyyyyyyy 110111xxxxxxxxxx

65536-1114111

4

UTF-16比起UTF-8,好处在于大部分字符都以固定长度的字节(2字节)存储,但UTF-16却无法兼容于ASCII编码。(来源维基)

 

番外:大端与小端

考虑一个2字节整数,在内存中存储这个数有两种方法:一种是将低字节放于起始地址,称为小端(little endian),另一种就是将高字节放于起始地址,称为大端(big endian)。IP协议使用大端字节序传送数据。本地的使用方式可能不同,看具体的硬件实现。


判断主机大端小端的程序:(来源于UNIX网络编程)

int main(){     union{          short s;         charc[sizeof(short)];}un;un.s = 0x0102;if(sizeof(short)== 2){     if(un.c[0] == 1 && un.c[0] == 2){         printf(“big endian”);}else if(un.c[0] == 2 && un.c[0] == 1)){     printf(“little endian”);}else     printf(“unknown\n”);}else     printf(“sizeof(short)=%d\n”, sizeof(short));exit(0);}


0 1
原创粉丝点击