历程:
ASCII开始,ASCII 码使用指定的7 位或8 位二进制数组合来表示128 或256 种可能的字符。
中国汉字那么多,显然不够么,于是沿用ASCII,大于127之后的所有两个字节的都表示一个汉字。
连标点符号都重新搞了,原本是在0-127之间的,所以0-127之间的标点符号是半角,后来编的叫全角符号。
成为GB2312,之后还扩展了GBK,GB18030.后来还有台湾同胞,香港人用繁体字,他们也扩展了ASCII,叫Big5,
日本也是,叫Shift_JIS,都用两个字节,也是第一个字节保持,第二个字节扩展。TIPS:GB2312,GBK,GB18030 Big5 Shift_JIS 这些字符集统称为ANSI。
在windows系统中,ANSI 编码代表 GBK,
在繁体中文Windows操作系统中,ANSI编码代表Big5,
在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码。
他们之间是不通用的。后面字符表就越来越多,ISO看不下去就定义了Universal Multiple-Octet Coded Character Set (UNICODE,也称UCS)。
很大气。所以一个汉字就是两个英文字符的时代过去了,所有英文也采用两个字节来处理。
ucs-2对应utf-16,ucs-4对应UTF-32。
一种编码的构成要素:
1.字库表(character repertoire)
2.编码字符集(coded character set)
3.字符编码(character encoding form)
1.字库表
一个相当于所有可读或者可显示字符的数据库,
字库表决定了整个字符集能够展现表示的所有字符的范围。
2.编码字符集(如:ASCII,Unicode)
也叫 “code point 表” ,用一个编码值 code point来表示一个字符在字库中的位置。
3.字符编码(如:Utf-8)
将编码字符集和实际存储数值之间的转换关系。就是说一个字母的实际编码后的存储值不一定是编码
字符集对应的位置的数值。字符编码就是确定存储值与编码集中位置数值的关系。一般来说都会直接将
code point的值作为编码后的值直接存储。
疑问1:
字库表和编码字符集看来是必不可少的,
那既然字库表中的每一个字符都有一个自己的序号,
直接把序号作为存储内容就好了。
为什么还要多此一举通过字符编码把序号转换成另外一种存储格式呢?
答:
统一字库表的目的是为了能够涵盖世界上所有的字符,
但实际使用过程中会发现真正用的上的字符相对整个字库表来说比例非常低。
例如中文地区的程序几乎不会需要日语字符,
而一些英语国家甚至简单的ASCII字库表就能满足基本需求。
而如果把每个字符都用字库表中的序号来存储的话,每个字符就需要3个字节
疑问2:
Unicode 与 Utf-8 是什么关系呀?
答:
Unicode呢就是一种编码字符集,一大串按序放置在那里的文字。有很多,所以还分了16部分。
Utf-8呢就是字符编码集的那个实现方式之一,就是字符编码。但它也就实现了Unicode中的1/16.
虽然它已经很通用了,但毕竟只实现了1/16,所以有些地方它还是不适用的。
Unicode介绍:
它没啥介绍的。就是很多字符,很多很多。0000-10FFFF的编号。
Utf-8介绍:
UTF-8编码为是一种变长编码方式,
最小编码单位(code unit)为一个字节,
每个字节的前1-3个bit为描述性部分,后面为实际序号部分。
规则如下:
Byte1 | Byte2 | Byte3 |
---|---|---|
0xxx xxxx | ||
110x xxxx | 10xx xxxx | |
1110 xxxx | 10xx xxxx | 10xx xxxx |
举例:
实际字符 | 在Unicode字库序号的十六进制 | 在Unicode字库序号的二进制 | UTF-8编码后的二进制 | UTF-8编码后的十六进制 |
---|---|---|---|---|
$ | 0024 | 010 0100 | 0010 0100 | 24 |
¢ | 00A2 | 000 1010 0010 | 1100 0010 1010 0010 | C2 A2 |
€ | 20AC | 0010 0000 1010 1100 | 1110 0010 1000 0010 1010 1100 | E2 82 AC |
疑问3:
为什么会乱码?
答:
乱码的英文是mojibake。
就好比是一个英国人为了表示祝福在纸上写了bless(编 码过程)。
而一个法国人拿到了这张纸,由于在法语中bless表示受伤的意思,
所以认为他想表达的是受伤(解码过程)
现在我们用utf-8编码连个字,编码后都是三个字节。
字符 | UTF-8编码后的十六进制 |
---|---|
很 | E5BE88 |
屌 | E5B18C |
连起来就是E5BE 88E5 B18C,然后用连个字节的GBK来解码。
两个字节的十六进制数值 GBK解码后对应的字符
E5BE |
88E5 |
B18C |
疑问4:
那Emoje呢。http://s1.51cto.com/wyfs02/M02/5B/27/wKioL1UBAwKzmU-oAAAxk5yKq2w329.png
答:
Unicode位于\u1F601-\u1F64F区段的字符
并且已经超越了目前常用的UTF-8字符集的编码范围\u0000-\uFFFF。
疑问5:
那些GB2312,GBK呢?
答:
GB2312,GBK啥的是字符编码,GB2312是对ASCII的扩展,GBK是对GB2312的扩展,此外还有GB18030,它又是对GBK的扩展。
就是在一步步添加各种汉字和罗马字符等,还有少数名族的字符。
疑问6:
“之前老说一个汉字两个字符”的由来是什么?
答:
疑问7:
字符集和字符编码的关系是不是一一对应的?
答:
「字符集」和「编码」等几个层次的概念被彻底分离且模块化的这样一个模型,其实是 Unicode 时代才得到广泛认同的。
而对于 ASCII、GB2312、Big5 之类的遗留(legacy)方案,其字符集及其编码的关系基本是锁定的,
所以常常用「字符编码」(character encoding)、「代码页」(code page)
等概念来统称它们那样从字符到编码字节流的整体方案。
比如 ASCII 本身就既是字符集又是编码方案,而 GB2312 用的都是 EUC-CN 编码方案。
疑问8:
为什么会有Unicode这种保存方式,它不是只有utf8 utf16 utf32三种实现方式吗?
答:
因为一些历史原因,Windows记事本的“Unicode”这个名号其实相当有误导性。这个编码实际上是UTF-16 LE。
平常使用的字符里,99%以上的字符都不会突破2个字节。所以很少直接使用Unicode直接保存。
除了UTF-32,UTF-8和UTF-16都是不定长的编码
语言 | 字符集 | 正式名称 |
---|---|---|
英语、西欧语 | ASCII,ISO-8859-1 | MBCS 多字节 |
简体中文 | GB2312 | MBCS 多字节 |
繁体中文 | BIG5 | MBCS 多字节 |
简繁中文 | GBK | MBCS 多字节 |
中文、日文及朝鲜语 | GB18030 | MBCS 多字节 |
各国语言 | UNICODE,UCS | DBCS 宽字节 |