我们都知道,在计算机的宇宙里,世界的中心是0,1,计算机也只能在磁盘上存储或者在网络上传输0,1,不能存储或者传输"你好"或者”Hello“之类的字符,那怎么把这些各式各样的人类字符存到计算机上或者在网络上传输呢?这就涉及到一个计算机编码问题。而,要搞懂计算机编码,就得区分三个基本概念,即字符、字符集和字符编码:
-
【字符】:像字母A, B, C,...,数字1, 2, 3,... ,汉字'你',’好‘,...,标点符号 , 。?等等我们称之为字符。
-
【字符集】:又称编码表,在计算机中,所有的东西都是以0,1二进制表示,而规定哪个二进制数字代表哪个字符,我们称之为字符编码工作。当把全球各个国家的所有字符都逐个编码,比如规定二进数1000001(十进制为65)表示英文字母A;二进数100111000101101(十进制为20013)表示中文的”中“;就形成一套字符编码文件,也就是我们说的字符集,比如ASCII字符集,GB2312字符集,Unicode字符集等。
那么,字符集有了,是不是问题就全部解决了呢,显然还没有,因为字符集只是一个标准规范,而标准规范和磁盘存储还不是一回事。比如,当我们在磁盘上存了一个01101100 01001001,计算机该如何解读这一串二进制数呢,如果计算机按照一个字节代表一个字符转换,通过与【Unicode字符集】比对,就会得到'l', 'I' 两个字符,而计算机如果按照二个字节代表一个字符转换,通过与【Unicode字符集】比对,就会得到 '汉'。那么,这个问题该怎么解决呢?这就涉及到我们下面谈到的字符集的字符编码问题,也就是字符如何存储的问题。
-
【字符编码】:也就是用于规定字符集在内存、硬盘或者网络传输中用使用多个字节存储的问题。比如我们常见的三种字符编码方式:
-
ASCII字符编码,用1个字节存储一个字符,也就是8个bit
-
UTF-8字符编码,使用1-6个字节,英文字母使用1个字节,中文使用3个字节,生僻字符使用4-6个字节。
-
比如,一个helloword.html文件以【UTF-8字符编码】格式保存,当用浏览器打开该文件时,浏览器会通过读取html文件的
,就会知道这个文件是按照【UTF-8字符编码】编码的,就会知道几个字节代表一个字符,比如当浏览器从文件中读取一串字节01101100 01001001时,它就会通过对照【Unicode字符集】,查找到这一串二进制数字对应的字符为"汉",而不会理解成一个字节代表一个字符,将这串二进制数翻译成'l', 'I' 两个字符。
下面简单总结一下计算机编码发展历史。
HTML字符编码
计算机信息(数字、文字、图片)是在磁盘和内存中是以二进制 1 和 0 进行存储的,如何以1和0表示世界上的各种文字与符号,我们称之为计算机字符编码问题。
从上世纪60年代至今,随着计算机不断发展,计算机字符编码出现或者经历了多个阶段:
1963 1980 1998 1991.10 1994 1996.07 ... 2020
───┴─────────┴──────────┴────────┴─────────┴───────────┴──────────────────┴─
ASCII GB2312 ANSI ISO-8859-1 Unicode1.0 Unicode2.0 ... Unicode13.0
ASCII码
1963年发布,用一个字节(8位)表示一个符号,只编码了128个字符,包括字母(a-z、A-Z),数字0-9 ,一些特殊符号! $ + - ( ) @ < > 。
GB2312及GBK
1980年发布,共收入汉字6763个和非汉字图形字符682个。1995年又颁布了GBK。GBK与GB 2312兼容,同时支持ISO/IEC10646—1和GB 13000—1的全部中、日、韩(CJK)汉字,共计20902字。
ANSI(也称Windows-1252)
1998年发布,对ASCII 进行了扩展,用一个完整的字节(8 位)来表示 256 个字符。Windows 95 及其之前的 Windows 系统中默认的字符集。
ISO-8859-1
1991年发布,对ASCII 进行扩展,用一个完整的字节(8 位)来表示 256 个不同字符。在HTML 2.0 中,默认的字符编码是 ISO-8859-1。 在HTML 4中若使用其他字符集,需在 标签中指定。
Unicode
1994年发布1.0,2020年发布13.0.0,为各种语言字符设定统一标准,目前,已收录超过13万个/字符,几乎覆盖了全球各国所有的文字和符号。比如,我们在Unicode官网查询"汉"字可以看到,"汉"在Unicode十进制数编码为27721。
The Unicode Standard (Version 3.2) | Your Browser |
---|---|
| 汉 |
Decimal | UTF-8 | UTF-16 | UTF-32 |
---|---|---|---|
27721 | E6 B1 89 | 6C49 | 00006C49 |
Unicode标准是一个符号库,规范了符号(比如"汉")和编码(27721)一一对应关系,但是字符在计算机上如何实现存储呢,也就是用1个字节,2个还是4个字节存储,这就涉及到Unicode的实现方式,即Unicode转换格式(Unicode Transformation Format,简称为UTF)问题,由于实现方式的不同,所以后续出现的UTF-8、UTF-16 、UTF-32等。
UTF-8(16, 32)字符编码
为了规范化Unicode 的存储问题,也就是规范化Unicode编码("汉"的十进制编码为27721)与物理存储(二进制0和1)的对应转换关系,相续出现了UTF-8、UTF-16和 UTF-32字符编码。
-
UTF-8 变长编码,用1~4个字节表示一个符号。
-
UTF-16 变长编码,用2个字节或4个字节表示表示一个符号;
-
UTF-32 定长编码,用4个字节表示表示一个符号;优点是检索速度快,缺点是浪费空间。
** Unicode 和 UTF-8 之间的转换关系表 ( x
字符表示码点占据的位 )**
码点的位数 | 字节数 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 |
---|---|---|---|---|---|---|---|
7 | 1 | 0xxxxxxx | |||||
11 | 2 | 110xxxxx | 10xxxxxx | ||||
16 | 3 | 1110xxxx | 10xxxxxx | 10xxxxxx | |||
21 | 4 | 11110xxx | 10xxxxxx | 10xxxxxx | 10xxxxxx | ||
26 | 5 | 111110xx | 10xxxxxx | 10xxxxxx | 10xxxxxx | 10xxxxxx | |
31 | 6 | 1111110x | 10xxxxxx | 10xxxxxx | 10xxxxxx | 10xxxxxx | 10xxxxxx |
Byte 1:0xxxxxxx
,用·个字节表示Unicode中的一个字符,除了0外,其他x位的7个bit的二进制数对应Unicode字符集中的一个字符的二进制数。
Byte 2:110xxxxx
10xxxxxx
,用2个字节表示Unicode中的一个字符,除了第一个字节的110和第二个字节的10外,其他所有x位共11个bit的二进制数对应Unicode字符集中的一个字符的二进制数。
Byte3,Byte4,Byte5,Byte6依次类推。
参考文献: