您的位置:首页 > 其它

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

2014-08-18 22:11 399 查看
豁然开朗,终于理顺了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)段,因此‘严’编码需要三个字节,即11100100
10111000 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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: