字符集和编码

1,字符集和编码的基础知识
在现实生活中,汉字包含了很多的字符,如'中','国','刘','宇','明',基于不同的目的,每个字符可能有不同的写法,比如'中'字在草书和行书中,写法是不同的.

那么人类社会抽象的字符在计算机里是怎么样表示的呢?

1)字符集
计算机不认识字符,只认识数字.因此,为了在计算机中表示所有汉字字符,需要为每个汉字字符指派一个惟一的数字(codepoint).
圈定一系列相关的字符,然后为这每个字符指定一个惟一的数字,这就是计算机中的字符集.

常见的字符集有:ASCII,ISO-8859-1.
ASCII共圈定了128个字符,包括阿拉伯字母,26个英文字母的大小写,和其它一些控制字符等,如回车.并为这每个字符惟一指定一个>=0, <=127的数字.如字符'a'在ASCII字符集中对应的数字是61.
ISO-8859-1共圈定了256个字符,包括128个ASCII字符,重音字符等.这个字符集基本包括了英语,西欧各国语言出现的字符.这每一个字符都惟一指定一个>=0,<=255的数字.其中,和ASCII中相同的字符有相同的数字影射,也就是说ISO-8859-1兼容ASCII字符集.如字符'a'在ASCII和ISO-8859-1字符集中对应的数字都是61.

现实中,由于存在很多抽象字符,所以每个国家或地区都制定了包含本国字符的字符集,如中国的gb2313,GBK.

2)编码
字符集中,字符对应一个数字,那么这些数字是如果存储到计算机中的呢? 因为计算机中都是0和1组成的,也就是说如何把一个数字和一串0和1对应上呢?这就是字符集的编码.

ASCII字符集的编码很简单,因为ASCII都是<=127的数字,所以每个ASCII字符集中的字符都可以用一个byte(8bits)来表示(最高位为0),如字符'a'为00111101
ISO-8859-1字符集包含的256个字符都可以用<=255的数字来表示,所以和ASCII一样,也可以用一个byte(8bits)来编码,字符'a'为也表示为00111101

而GBK字符集呢? 因为GBK字符集包含了21886个字符,也就是说用一个byte的编码是不够的,那么,是用两个字节的编码吗?试想一下,如果用两个字节(双字节)编码,那么字符'a'的编码就应该是0000000000111101,那么就和ASCII编码不兼容了,因为按ASCII编码的规定,这两个字节0000000000111101代表的是两个字符,而不是一个.当你一个用GBK字符集编码的文件包含的全是些英文字符,然后用ASCII编码的方式打开,就会出现乱码.事实上,为了兼容ASCII字符集编码,GBK字符集采用的编码是一个字节或者两个字节,<=127的用一个字节,>127的用两个字节.

不单单是GBK,那些包含很多字符的字符集采用的编码都和GBK的编码类似,用一个或两个字节来表示一个字符,并且都兼容ASCII.

上面说了这么多,你可能会很迷茫,GBK到底是指字符集还是指编码呢? 因为通常一个字符集的编码方式只有一种,所以GBK这个名词既指的是字符集也是编码.

就像汉字可能有行书和草书一样,有些字符集可能有不止一种编码.Unicode就是这样的例子.Unicode是一个字符集,但编码有UTF-8,UTF-16,UTF-32三种.

2,Unicode
为了包含本国,本地区,或者需要特定用途的字符,出现了很多字符集.但第一,它们都不完全,都只是包含了这个世界上一部分的字符,第二,它们之间互相不兼容,如在GBK字符集中,'中'的codepoint是OxD6D00D0A,而在BIG5字符集中,'中'的codepoint是OxA4A40D0A,Unicode字符集的出现就是为了解决这些问题,它试图用一个字符集来包括全世界所有的字符,包括现今正使用的,或者是已经不再使用的,比如中国的甲骨文.

起初,在Unicode4.0之前,Unicode只定义了6万多个字符,最新Unicode版本是5.0,共包含了9万多个字符,几乎包括了人类社会所有的字符.

Unicode字符集共有三种编码方式,分别是UTF-8,UTF-16,UTF-32.

1)UTF-32
很简单,就是每个codepoint用32个bits来编码.比如'a'的codepoint是61,因此编码成000000000000000000111101,可见,它和ASCII编码并不兼容.因为它用了四个字节.
2)UTF-16
codepoint在范围U+0000..U+D7FF, U+E000..U+FFFF的,用16个bits来编码,codepoint在范围U+10000..U+10FFFF的,利用代理对,用32个bits来编码.因此UTF-16也是和ASCII编码不兼容的.
3)UTF-8
为了兼容ASCII编码,UTF-8用8bits做为一个单元(code unit)来对字符编码,在这种编码方式下,ASCII字符的编码还是和ASCII编码中一样,但有一些字符就会胖,需要3个或以上的byte.


Unicode字符codepoint         UTF-8编码

00000000 - 0000007F        0xxxxxxx
00000080 - 000007FF        110xxxxx 10xxxxxx
00000800 - 0000FFFF        1110xxxx 10xxxxxx 10xxxxxx
00010000 - 001FFFFF        11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
00200000 - 03FFFFFF        111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
04000000 - 7FFFFFFF        1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx


比如字符'a',它的codepoint是61(Ox3D),在第一个区间,因此它的UTF-8编码是:00111101,和在ASCII中的编码一样.

字符'汉',它的codepoint是27721(Ox6C49),在第三个区间,因此它的UTF-8编码是:11100110,10110001,10001001,.需要三个字节.

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值