问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

程序员必备:必须弄懂的字符编码

创作时间:
作者:
@小白创作中心

程序员必备:必须弄懂的字符编码

引用
1
来源
1.
https://juejin.cn/post/7338691767435575331

在计算机世界里,所有的文字都是由0和1组成的字符串。为了让汉字正常显示在屏幕上,我们需要设计一套字符编码系统。本文将深入探讨ASCII、GB2312、GBK、GB18030、UTF8等常见编码方式的原理和应用,帮助程序员更好地理解字符编码的本质。

一、字符编码的基本原理

让我们思考一下,为了让汉字正常显示在屏幕上,我们需要做些什么:

  1. 给所有的汉字一个独一无二的数字编号,建立一个数字编号到汉字的映射关系(即字符集)
  2. 把这个数字编号用0和1表示出来

我们设计一个简单的中文编码方案:

第一步:规定每个中文占用的字节数

我们知道一个字节有8位,最多可以表示2^8=255个字符。而中文收录大约有91251个字符,因此我们需要规定每个中文占用2个字节,不足的部分用0补齐。

为了区分中文字符和其他字符,我们规定:

  • 第一个字节的前两位二进制固定为10
  • 第二个字节的第一位固定为0

第二步:数字与中文的映射关系

例如:

  • 编码1号中文:“我” ,10 000000 - 0 0000001
  • 编码3号中文:“你” ,10 000000 - 0 0000011
  • 编码9号中文:“爱” ,10 000000 - 0 0001001
  • ...
  • 编码号n中文:“结” ,10 011111 - 0 111 0011

第三步:翻译报文成中文

当我们收到一个01报文时,应该如何翻译成中文呢?由于我们规定每个中文字的第一个字节以10开头,这样就可以正确地分割报文。如果没有这个规定,报文的分割就会变得非常困难。

通过这个简单的例子,我们可以大致理解字符编码是如何工作的。但实际的编码处理会比这个更为复杂。

二、编码的基本概念

在深入探讨具体编码方式之前,我们先来了解一下几个基本概念:

1. 字符(Character)

具有语义价值的最小文本单位。简单来说,字符包括各种文字和符号,如中文汉字、英文字母、阿拉伯数字、标点符号等。

2. 字符集(Character Set)

多个字符的集合。例如,拉丁字符集被英语和大多数欧洲语言使用,而希腊字符集仅被希腊语言使用。不同的字符集包含的字符个数、字符种类以及编码方式都可能不同。

3. 字符编码(Character Encoding)

一种映射规则,将每个字符对应到一个唯一的数字。根据这个映射规则,可以将字符转换为计算机可以存储和传输的形式。

4. 码点(Code Point)

在某个字符集中,根据某种编码规则将字符编码后得到的值。例如,在ASCII字符集中,字母A的码点是65。

三、ASCII编码

20世纪60年代,美国制定了一套字符编码规则,对英语字符与二进制位之间的关系做了统一规定,这就是ASCII编码。ASCII编码一直沿用至今。

ASCII编码规定了128个字符的编码规则,这128个字符形成的集合就叫做ASCII字符集。在ASCII编码中:

  • 每个字符占用一个字节的后面7位,最前面的1位统一规定为0
  • 0-31是控制字符,如换行、回车、删除等
  • 32-126是可打印字符,可以通过键盘输入并显示出来

扩展ASCII编码(Extended ASCII)

由于ASCII是针对英语设计的,当处理带有音调标号的欧洲文字时就会出现问题。为了表示更多字符,人们将最高位也用于字符表示,这就是扩展ASCII编码。扩展ASCII字符集包括255个字符。

然而,即使扩展ASCII字符集也不能统一欧洲的语言环境,因此形成了多个子标准,如ISO-8859系列:

  • ISO-8859-1(Latin-1):西欧常用字符,包括德法两国的字母
  • ISO-8859-2(Latin-2):东欧字符
  • ISO-8859-3(Latin-3):南欧字符

对于亚洲国家的文字,使用的符号更多,例如简体中文常见的编码方式是GB2312,使用两个字节表示一个汉字,理论上最多可以表示65536个符号。

四、汉语编码

汉字编码根据应用目的的不同,大致可分为以下几种:

  1. 外码(输入码):用于将汉字输入到计算机中的一组键盘符号,如拼音码、五笔字型码等。
  2. 交换码(国标码):中国国家标准GB2312-80《信息交换用汉字编码字符集——基本集》是一个四位十六进制数,从0x2020开始。区位码则是国标码的另一种表现形式,是一个四位的十进制数,将汉字和图形符号组成一个94×94的方阵,分为94个区(01-94),每区包含94个位(01-94),全部元素或位置=94×94=8836个,其中7445个位置分配给汉字和图形字符,其余的1391个位置保留备用。
  3. 机内码:是区位码(国标码、交换码)在计算机内部的二进制具体表示,GB内码的存储格式始终是big endian,即高位在前。
  4. 字形码:谈不上说是什么具体的码值,只不过是个约定成俗的叫法而已,其实是一个图形点阵结构(常用是16×16点阵)。
  5. 地址码:汉字地址码是指字库中逻辑地址码,与汉字内码有着简单的对应关系易于相互转换。

常见国标码有以下几种:

  1. GB 2312-1980:信息交换用汉字编码字符集、国标码的基本集、7445个字符、CP936
  2. GBK-1995:汉字内码扩展规范、21886个字符、CP936
  3. GB13000.1-1993:通用多八位编码字符集用于信息技术
  4. GB18030-2000:信息交换用汉字编码字符集、基本集的扩充、27484字符、CP54936、不支持手机与MP3

GBK编码和GB18030编码

GB2312支持的汉字太少。1995年的汉字扩展规范GBK1.0(此编码为微软为简体中文用户设计的),全称《汉字内码扩展规范》(GBK),英文名称 Chinese Internal Code Specification,GBK包括了GB2312 的所有内容,同时又增加了近20000个新的汉字(包括繁体字)和符号,共收录了21886个符号,它分为汉字区和图形符号区。汉字区包括21003个字符。

我们国家是个多民族国家,各个民族几乎都有自己独立的语言系统,为了表示那些字符,于是2000年的GB18030取代GBK1.0正式成为国家标准。该标准收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。

中文编码之间存在兼容性

这也是平时业务中最常见的导致乱码场景,使用UTF8去读取GBK编码的文字,可能会看到各种乱码。GB系列的几种编码,GB18030兼容GBK,GBK又兼容GB2312

五、Unicode编码

对于全世界各国语言都不同很难全部包含在内,上面说的编码太多太过于杂乱所以就出现了Unicode字符集。Unicode赋予了全世界所有文字和符号一个独一无二的数字编号

它定义了一种统一的多语言文本编码方式,使文本数据能够在国际上交换,并为全球软件奠定了基础。Unicode是通用字符编码(universal character encoding)标准,由ISO(The International Organization for Standardization)与Unicode联盟(Unicode Consortium)共同开发与维护。

之所以称之为Unicode而不ISO 10646,只不是Unicode这个名字更容易记住而已。

Unicode三种编码

Unicode标准定义了三种编码形式(UTF-8、UTF-16、UTF-32),允许以字节、字或双字为的格式(即代码单位是8位、16位或32位)存储和传输相同的数据。

UTF-8介绍

UTF-8:以8位(byte)字节位基本单元的可变长度编码,根据字符的需要,将每个字符编码可以是1-4个字节。
UTF-8数据兼容ASCII数据,ASCII字符都以UTF-8编码为一个字节,该字节与ASCII中的编码相同。后面会讲UTF的编码格式。
UTF-8数据与GB码不兼容。例如“汉”字的Unicode编码是6C49,而GB码是BABA。
BMP中的所有字符都以UTF-8编码为一个、两个、三个字节。其他平面中的字符以UTF-8编码为四个字节。
UTF-8有三个主要优点:
它完全兼容ASCII,ASCII数据可以被视为UTF-8数据。
它不要求所有字符都使用两个或更多字节的存储空间。
统一的多语言文本编码方式。

UTF-16

UTF-16:16位可变长度编码。 UCS-2的一种扩展,若要引用BMP以外的平面上的字符,则通过组合两个UCS-2代码单元(code unit)来指定单个非BMP字符。

UTF-32

UTF-32:32位固定长度编码,相当于UCS-4。

UTF-8 的编码规则

UTF-8 的编码规则如下:

  • 对于单字节的字符,字节的第一位设为 0,后面 7 位为其代码点。
  • 对于 n 字节的符号( n > 1),第一个字节的前 n 位都设为 1,第 n + 1 位设为 0,后面字节的前两位一律设为 10 。剩下的没有提及的二进制位,全部为为其代码点。

下图是字符的UTF-8编码的示例:

每个字符在UTF-8中表示为最多4个字节的序列,其中第一个字节表示多字节序列中要遵循的字节数,从而实现高效的数据解析。

数据库与Unicode

MySQL支持两种UTF-8变体:

  • utf8mb4:这是自MySQL 5.5以来支持的完整UTF-8字符集
  • utf8:也称为utf8mb3。这只支持Unicode 3.0的基本多语言平面,不支持4字节字符。

在MySQL中,按列使用字符集。新列的默认字符集设置在表级别。表的默认值是在数据库级别设置的。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号