跳转至

8. MySQL字符集和排序规则

字符

字符(Charcter)是文字与符号的总称,包括文字、图形符号、数学符号等。26个英文字母属于字符,每个汉字也属于一个字符。

众所周知,计算机底层处理的都是二进制数字。计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。

最早的计算机在设计时采用8个二进制比特位(bit)作为一个字节(byte)。

所以,一个字节能表示的最大的整数就是255(二进制11111111=十进制255),如果要表示更大的整数,就必须用更多的字节。

比如:两个字节可以表示的最大整数是65535,四个字节可以表示的最大整数是4294967295。

字符编码和字符集

字符集

在人类日常生活中,有数学上的各种数学运算符,古希腊数学符号,也有各国日常语言:拉丁文,英文,中文,日文,韩文等等。

甚至还有繁体中文字,以及令人头疼的中文生僻字。

字符集字面上的理解就是字符的集合,是**一个自然语言文字系统支持的所有字符的集合**。这个集合称为字符集。

也就是说,我们可以 人为的根据某种规则归纳一些我们使用的文字/符号,这些文字/符号的集合就称为一个字符集 ,并且可以根据不同的规则划分成不同的字符集。

字符编码

二进制(binary)

binary 众所周知,计算机底层存储和处理数据只是一大堆二进制的0和1

如果要想让计算机识别我们人类的文字、符号、数字,就需要一个转换规则,把我们人类使用的各种字符转换成计算机认识的二进制,也就是0和1。

字符集和二进制的映射编码规则就称为 字符编码规则 。接下来简单介绍一下几种早期的编码规则:

由于历史的原因,早期一般认为字符集和字符编码是同义词,并不需要进行严格区分。

因此在像ASCII这样的简单字符集为代表的传统字符编码模型中,这两个概念的含义几乎是等同的。

ASCII编码

由于计算机是美国人发明的。因此,最早只有127个英文字符被编码到计算机里,也就是大小写英文字母、阿拉伯数字和一些符号,这个编码表被称为 ASCII编码(美国信息互换标准代码)

在 ASCII 编码规范中:大写字母 A 的编码是65,小写字母 z 的编码是122。

ASCII码一共规定了128个字符的编码(包括32个不能打印出来的控制符号),比如空格 SPACE 的 ASCII 码是32(二进制表示为 00100000),大写的字母 A 的ASCII 码是65(二进制表示为 01000001)。这128个符号只需要占用了一个字节的后面7位,最前面的一位统一规定为0。

ASCII字符集最大的缺点就是只能显示26个基本拉丁字母、阿拉伯数字和英式的标点符号,以及控制字符(回车键、退格、换行键等),因此只能用于显示现代美国英语。

https://www.ascii-code.com/

https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html

https://zhongwenzidian.18dao.cn/node/20707

但是要处理中文显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突,所以,中国制定了GB2312编码,用来把中文编进去。

全世界有上百种语言,日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里,各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。

Unicode字符集

在中国发展出以上字符集合字符编码的同时,计算机也在世界各个国家迅速普及和发展着,每个国家为了使计算机能够显示当地语言和符号,也纷纷设计出了各种字符集和字符编码规则。

每个国家搞一套,在自己国家使用没问题,但随着互联网的兴起,使得各个国家的计算机都接入到互联网,信息的交流和通信越来越多,但由于编码规则不同,很快就出现了不兼容的乱码现象。

为了解决这个问题,迫切需要一个统一的字符集,能够涵盖世界各个国家的文字和符号,这个字符集就是Unicode字符集。

Unicode字符集每年都在修订和更新中,持续不断地纳入新的文字和字符。

Unicode字符集编码是由一个名为Unicode学术学会(Unicode Consortium)的机构制订的字符编码系统,支持现今世界各种不同语言的书面文本的交换、处理及显示。

Unicode 源于一个很简单的想法:将全世界所有的字符包含在一个集合里,计算机只要支持这一个字符集,就能显示所有的字符,再也不会有乱码了。

它从 0 开始,为每个符号指定一个编号,这叫做“码点”(code point)。比如,码点 0 的符号就是 null(表示所有二进制位都是 0)。

该编码于1990年开始研发,1994年正式公布。最新的Unicode版本是14.0.0,共包含了 144697 个字符。

http://www.unicode.org/versions/Unicode14.0.0/

Unicode字符编码的优缺点

Unicode字符编码的优点是能覆盖世界上任何一种语言所用的文字符号,但缺点也很明显,我们常用的文字字符都是采用2个字节16位编码,这在进行字符存储和网络传输时,消耗的资源是比较大的。

例如,如果一个仅包含基本7位ASCII字符的Unicode文件,如果每个字符都使用2字节的Unicode编码传输,其第一字节的8位始终为0,这就造成了比较大的浪费。

为了解决这个问题,节省存储空间、提高网络传输效率,提出了Unicode转换格式(Unicode Transformation Format),简称UTF。

UTF-32、UTF-16、UTF-8都是为了转换Unicode码所制定的各种转换方案。

UTF编码

UTF-8 是一个字符编码系统。它可以让你将字符表示为 ASCII 文本,同时还允许使用国际字符,如中文字符。

截至 2020 年代中期,UTF-8 是最流行的编码系统之一。

文本文件和二进制文件

数据在计算机中存储在物理上是二进制的,所以文本文件与二进制文件的区别并不是物理上的,而是逻辑上的。这两者只是在编码层次上有差异。

简单来说,文本文件是基于字符编码的文件,常见的编码有ASCII编码,UNICODE编码等等。

二进制文件是基于值编码的文件,你可以根据具体应用,指定某个值是什么意思(这样一个过程,可以看作是自定义编码)

字符存储到文件时,根据使用的字符集找到这个字符在这个字符集中的字符值,然后根据指定的编码方式将这个字符值编码为二进制字节形式存储到文件中,常见的编码方式有 ASCII、UNICODE、UTF-8 等;指定编码方式后,每个字节(也可以是每两个、三个字节)所表示的字符是一样的,任何程序都可以正确读取。二进制文件是自定义编码的,也就是说,你可以根据具体程序指定每个字节(或者每两个、三个字节)代表什么意思。例如,A 程序是图像编辑器,指定 01001111 代表红色,B 程序是视频播放器,它把 01001111 理解为快进,显然是不对的。所以,字符文件是通用的,任何程序只要按照对应的编码方式打开都可以正确显示

MySQL中的字符集

character set 。想要把各种人类可以理解的字符存储到计算机中,就需要建立字符与二进制数字的映射关系。

字符集就是这样的一种映射关系,不同的字符集表示的字符数量不同,字符集越大,所能表示的字符越多,需要占用的二进制位更多,需要的磁盘空间就越大。

在 MySQL 中,字符集的概念和编码方案被看做是同义词,一个字符集是一个转换表和一个编码方案的组合。

我们可以为 MySQL 服务器、数据库、表、字符类型的字段以及字符串常量指定一个字符集(Character Set)和排序规则(Collation)。

MySQL 中所支持的字符集存在 information.CHARACTER_SETS 表中,其中 utf8mb4 字符集兼容性最好,它可以存各种语言的字符,包括 emoji 表情等。

MySQL的utf8并不是真正意义上的utf8,MySQL的utf8只支持最长三个字节,所以Emoji 表情和有些生僻字以及任何新增的 Unicode 字符等如果超过三个字节用utf8字符集保存是会报错的。

MySQL 中的 utf8mb4 字符集就是 MySQL 对 Unicode 字符集的具体实现,参考

MySQL 8.0 开始,默认字符集被改为 utf8mb4,而不是之前的 latin1 ,utf8mb4 中的一个字符最多占用 4 个字节。

-- 查看MySQL支持的所有字符集种类
SHOW CHARACTER SET;
select * from information_schema.character_sets;

-- 查看当前MySQL Server配置的各种层面的字符集
show VARIABLES like "%character_set%"



-- 建库指定库级别的字符集,如果不指定,默认会从character_set_database这个变量继承
CREATE schema qhdata_inspect DEFAULT charset utf8mb4 collate utf8mb4_general_ci;

-- 建表指定表级别的字符集,也可以对字段设置字符集

-- MySQL 字符集和排序规则的优先级别为字段级别大于表级别,表级别大于数据库级别,数据库级别大于服务器级别。
CREATE TABLE  IF NOT EXISTS demo.test(
        `org_name` VARCHAR(20) NOT NULL CHARACTER SET utf8mb4  COLLATE utf8mb4_general_ci  ,
        `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP,        
)
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


-- MySQL 中的字符串常量也有字符集和排序规则。例如,以下字符串常量使用相同的字符集:
SELECT '数据库';
SELECT _utf8mb4'数据库';
SELECT _utf8mb4'数据库' COLLATE utf8mb4_0900_ai_ci;



--修改表的字符集和字段的字符集

-- 对已存在的表修改字符集,只是修改了后续新增列的默认字符集。对于已存在的列字符集,并没有改变。
ALTER TABLE emoji_test CHARSET utf8mb4;

-- 正确修改列字符集的命令应该使用 ALTER TABLE ... CONVERT TO...这样才能将之前的列 a 字符集从 UTF8 修改为 UTF8MB4
ALTER TABLE emoji_test CONVERT TO CHARSET utf8mb4;


--LENGTH(column) 函数返回以字节为单位的字符串长度,多字节字符集中字符占用的字节数可能不同
--CHAR_LENGTH(column) 函数返回以字符为单位的字符串长度。

排序规则

在 SQL 中,经常有排序或比较等场景。

collation,检验规则,又称为排序规则,一般是用于比较字符的一套规则,即字符的排序规则。比如有的规则区分大小写,有的则无视。

世界上的文字很多,所以才会有“不区分音调”的要求,这时候e、ē、é、ě、è就是等价的。

那么假设我们要进行拼音查找,只要按e去找就可以全部列出来,很方便。甚至,它们也和ê、ë也是等价的,这样就更方便了。

每种字符集都可能有多种检验规则,并且都有一个默认的检验规则(information_schema. CHARACTER_SETS.DEFAULT_COLLATE_NAME)

SHOW COLLATION WHERE Charset = 'utf8mb4';

select * from information_schema.COLLATIONS;

每个校验规则只能用于一个字符集,因此字符集与校验规则是一对多的关系。

MySQL字符集和排序规则优先级:MySQL 字符集和排序规则的优先级别为字段级别大于表级别,表级别大于数据库级别,数据库级别大于服务器级别。

校验规则存储在 information_schema.COLLATIONS 表中。对于 utf8mb4 字符集,一般建议使用 utf8mb4_general_ci 排序规则。参考

  • 排序规则命名惯例:字符集名_对应的语言排序规则_Unicode版本_ai/as/ci/cs/ks/bin

  • 字符集名:这个很好理解,表示排序规则属于对应的字符集。不同字符集之间的字段肯定是无法比较的。

  • 对应语言的排序规则:比如utf8mb4_zh_0900_as_cs中的zh就是表示汉字的排序规则,它规定字段按照中文拼音进行排序。

  • 如果是unicode字符集,那么可能会有unicode版本标识,比如MySQL8.x中的_0900_ai_ci排序规则中的0900就是表示规则基于Unicode 9.0

  • 排序后缀,可以用于表示是否区分大小写,是否区分口音等等,对于中文基本上可以忽略。

常见utf8mb4字符集中的排序规则:

  • utf8mb4_unicode_ci is based on the official Unicode rules for universal sorting and comparison, which sorts accurately in a wide range of languages.

  • utf8mb4_general_ci is a simplified set of sorting rules which aims to do as well as it can while taking many short-cuts designed to improve speed. It does not follow the Unicode rules and will result in undesirable sorting or comparison in some situations, such as when using particular languages or characters.

https://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci

MySQL 8.0 默认使用 utf8mb4 字符集,默认的排序规则为 utf8mb4_0900_ai_ci,表示不区分重音和大小写。

-- 对于MySQL8.0的默认utf8mb4字符集和utf8mb4_0900_ai_ci默认排序规则。执行如下查询:


SELECT 'a'  = 'A' ;                                     /*结果是1*/
SELECT 'a' COLLATE utf8mb4_zh_0900_as_cs  = 'A' ;       /*--结果是0*/

-- 因为utf8mb4_0900_ai_ci默认不区分英文大小写,所以它认为"a"和"A"是相等的两个字符。

中文字段排序

-- 对于中文而言,排序方式与英文有所不同;中文通常需要按照拼音、偏旁部首或者笔画数进行排序。

-- MySQL8.0中,默认使用utf8mb4字符集,这个字符集默认使用的排序规则是 utf8mb4_0900_ai_ci ,它默认是对于中文按照偏旁部首进行排序。

SELECT emp_name FROM employee ORDER BY emp_name;


emp_name  |
----------|
关兴      |
关平      |
关羽      |
刘备      |
周仓      |
孙丫鬟    |
孙乾      |
孙尚香    |
庞统      |
廖化      |
...


-- 可以在查询时指定排序规则,select中的collate子句可以用在 order by子句,group by、having、聚集函数、别名等
-- 对于 utf8mb4 字符集,如果设置 utf8mb4_zh_0900_as_cs 排序规则,那么就可以按照中文拼音进行排序。

SELECT emp_name FROM employee ORDER BY emp_name collate 'utf8mb4_zh_0900_as_cs';
emp_name |
----------|
邓芝      |
法正      |
关平      |
关兴      |
关羽      |
黄权      |
黄忠      |
简雍      |
蒋琬      |
廖化      |
...


-- 也可以将数据转换为其他支持特定排序规则的字符集,例如 gbk 字符集默认的 gbk_chinese_ci 排序规则就是按照拼音进行排序:
SELECT emp_name FROM employee  ORDER BY convert(emp_name using gbk);

常见字符集和字符编码

MySQL字符集设置大概分为两类:

  • 创建对象的默认值。级别依次从高到低,低级别如果未指定,自动继承高级别。
级别 配置参数 是否可配置 是否可创建时指定 建议值
Server character_set_server 不可 建议在/etc/my.cnf配置为utf8mb4,创建时不单独指定
Database character_set_database 可以 建议在/etc/my.cnf配置为utf8mb4,创建时不单独指定
Table 默认继承库字符集 可以 建议直接继承上级,特殊情况可以单独指定
Collum 默认继承表字符集 可以 建议直接继承上级

utf8字符集下默认的比较规则是utf8_general_ci,日常中会用到的有utf8_general_ciutf8_unicode_ciutf8_bin三种比较规则,其他比较规则基本很少会用,下面简单了解下这三种比较规则的异同。

首先utf8_bin的比较方法其实就是直接将所有字符看作二进制串,然后从最高位往最低位比对。所以很显然它是区分大小写的。而utf8_general_ci和utf8_unicode_ci是不区分大小写的。

utf8_general_ci和utf8_unicode_ci对中、英文来说没有实质的差别。utf8_unicode_ci的最主要的特色是支持扩展,即当把一个字母看作与其它字母组合相等时。例如,在德语和一些其它语言中‘ß'等于‘ss'

utf8_general_ci是一个遗留的比较规则,不支持扩展。它仅能够在字符之间进行逐个比较。这意味着utf8_general_ci比较规则进行的比较速度很快,但是与utf8_unicode_ci相比,比较正确性较差。

# 创建表 指定列为不同的排序规则
mysql> create table utf8_test (
    -> col_general varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci,
    -> col_unicode varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci,
    -> col_bin varchar(20) CHARACTER SET utf8 COLLATE utf8_bin
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 # 插入数据,每行数据各个字段值一样
 mysql> select * from utf8_test;
+-------------+-------------+---------+
| col_general | col_unicode | col_bin |
+-------------+-------------+---------+
| MySQL       | MySQL       | MySQL   |
| mysql       | mysql       | mysql   |
| A           | A           | A       |
| a           | a           | a       |
| aA          | aA          | aA      |
+-------------+-------------+---------+
# 查询
mysql> select * from utf8_test where col_general='mysql';
+-------------+-------------+---------+
| col_general | col_unicode | col_bin |
+-------------+-------------+---------+
| MySQL       | MySQL       | MySQL   |
| mysql       | mysql       | mysql   |
+-------------+-------------+---------+
mysql> select * from utf8_test where col_unicode='MySQL';
+-------------+-------------+---------+
| col_general | col_unicode | col_bin |
+-------------+-------------+---------+
| MySQL       | MySQL       | MySQL   |
| mysql       | mysql       | mysql   |
+-------------+-------------+---------+
# 验证,只有utf8_bin类型的字段区分大小写
mysql> select * from utf8_test where col_bin='mysql';       
+-------------+-------------+---------+
| col_general | col_unicode | col_bin |
+-------------+-------------+---------+
| mysql       | mysql       | mysql   |
+-------------+-------------+---------+
# 排序 发现不同排序规则对顺序有影响
mysql> select * from utf8_test order by col_general;
+-------------+-------------+---------+
| col_general | col_unicode | col_bin |
+-------------+-------------+---------+
| A           | A           | A       |
| a           | a           | a       |
| aA          | aA          | aA      |
| MySQL       | MySQL       | MySQL   |
| mysql       | mysql       | mysql   |
+-------------+-------------+---------+
mysql> select * from utf8_test order by col_bin;
+-------------+-------------+---------+
| col_general | col_unicode | col_bin |
+-------------+-------------+---------+
| A           | A           | A       |
| MySQL       | MySQL       | MySQL   |
| a           | a           | a       |
| aA          | aA          | aA      |
| mysql       | mysql       | mysql   |
+-------------+-------------+---------+

关于字符集和排序规则建议

对于MySQL 5.7版本,一般情况下建议将字符集改为utf8,比较规则选择默认的utf8_general_ci。

utf8_general_ci相对于utf8_unicode_ci来说校对速度快,但是如果你的应用有德语、法语或者俄语,建议使用utf8_unicode_ci。

如果某个表或列字段要求区分大小写,可以单独指定该表或字段使用utf8_bin比较规则。

https://cloud.tencent.com/developer/article/1630141

字符padding

排序规则中,有个填充属性。

计算中的常见中文字符集

GB2312-80 字符集

GB/T 2312GB 2312-80中国国家标准简体中文字符集 ,全称《信息交换用汉字编码字符集·基本集》,又称 GB0,由中国国家标准总局发布,于 1981 年 5 月 1 日实施。

GB/T 2312 编码通行于中国大陆;新加坡等地也采用此编码。中国大陆几乎所有的中文系统和国际化的软件都支持 GB 2312

GB/T 2312 标准共收录 6763 个汉字,其中一级汉字 3755 个,二级汉字 3008 个;同时收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的 682 个字符。

GB/T 2312 的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75% 的使用频率。对于人名、古汉语等生僻字,GB 2312 不能处理,这导致了后来 GBK 及 GB 18030 汉字字符集的出现。

GB/T 2312 对任意一个图形字符都采用两个字节表示,并对所收汉字进行了"分区"处理,每区含有 94 个汉字/符号,分别对应第一字节和第二字节。这种表示方式也称为**区位码**。

  • 01-09 区为特殊符号。
  • 16-55 区为一级汉字,按拼音排序。
  • 56-87 区为二级汉字,按部首/笔画排序。
  • 10-15 区及 88-94 区则未有编码。

GB/T 2312 的编码范围为 2121H-777EH,与 ASCII 有重叠,通行方法是将 GB 码两个字节的最高位置 1 以示区别。

GBK字符集

GBK 即汉字内码扩展规范,K 为汉语拼音 Kuo Zhan(扩展)中“扩”字的声母。英文全称 Chinese Internal Code Specification。GBK共收入 21886 个汉字和图形符号,包括:

  • GB 2312 中的全部汉字、非汉字符号。
  • BIG5 中的全部汉字。
  • 与 ISO 10646 相应的国家标准 GB 13000 中的其它 CJK 汉字,以上合计 20902 个汉字。
  • 其它汉字、部首、符号,共计 984 个。

GBK 向下与 GB 2312 完全兼容,向上支持 ISO 10646 国际标准,在前者向后者过渡过程中起到的承上启下的作用。

GBK 采用双字节表示,总体编码范围为 8140-FEFE 之间,首字节在 81-FE 之间,尾字节在 40-FE 之间,剔除 XX7F 一条线。GBK 编码区分三部分: 汉字区 包括 - GBK/2:0XBOA1-F7FE, 收录 GB 2312 汉字 6763 个,按原序排列; GBK/3:0X8140-AOFE,收录 CJK 汉字 6080 个; GBK/4:0XAA40-FEAO,收录 CJK 汉字和增补的汉字 8160 个。 图形符号区 包括 GBK/1:0XA1A1-A9FE,除 GB 2312 的符号外,还增补了其它符号 GBK/5:0XA840-A9AO,扩除非汉字区。 用户自定义区 GBK 区域中的空白区,用户可以自己定义字符。

GB18030字符集

GB 18030 是中国政府规定的中文文字集和编码标准。更新 2022 支持扩展字符,自 2023 年 8 月 1 日起生效。

GB18030编码采用单字节、双字节、四字节分段编码方案,具体码位见下文。GB18030向下兼容GBK和GB2312编码。

国家标准GB18030-2005《信息技术 中文编码字符集》是我国继GB2312-1980GB13000-1993之后最重要的汉字编码标准,是我国计算机系统必须遵循的基础性标准之一。

GB18030有两个版本:GB18030-2000GB18030-2005

  • GB18030-2000是GBK的取代版本,它的主要特点是在GBK基础上增加了CJK统一汉字扩充A的汉字。

  • GB18030-2005的主要特点是在GB18030-2000基础上增加了CJK统一汉字扩充B的汉字。

  • GB18030-2022《信息技术-中文编码字符集》是当前最新版本,为国家市场监督管理总局和国家标准化管理委员会于2022年7月19日发布、2023年8月1日实施。

    此版本在保留总体结构的基础上,从条文强制改为全文强制,但增加了「实现的级别」一章,定义了三个实现级别,并要求「任何本文件使用的产品均应满足实现级别1」,与上一版的「部分强制」相比,实际要求「增加四字节编码部分的CJK统一汉字」的 66 字。另外,该版本完整覆盖 2013 年发布的《通用规范汉字表》,在资料性附录E中明确了《通用规范汉字表》8105 个汉字的代码位置,并规定要通过「实现级别2」来支持。

相对于 GB18030-2005 版本,它做了较多的修改,最典型的是又增加了不少汉字。

  • 总数从 70195 增加到了 87887 个,并且终于覆盖了《通用规范汉字表》 的全部汉字。

  • 少数民族文种从 6 种增加到了 10 种

  • 标准也从部分强制变成了全文强制

  • 有三种实现级别的要求:

    • 对于所有具备中文信息处理能力的产品都得支持级别一,包含 27584 个汉字

    • 操作系统、 数据库、中间件等基础软件的,至少要支持到级别二,比级别一增加了《通用规范汉字表》中的 196 个汉字

    • GB/T 4754 《国民经济行业分类》中所有行业领域用于政务服务和公共服务的信息技术产品和信息化系统全面强制执行实现级别三,包含本标准内全部87887个汉字。

GB18030-2022 新标准支持的汉字有很多,如:

0x82359334  U+9FCF 鿏
0x82359339  U+9FD4 鿔 (我的旧电脑还是显示不出来)

全角半角

全角符号是双字节中文编码的历史遗留问题。当年在纯文本的界面中,为了让西文和中日韩的方块字对齐,就让西文字母、数字和标点也占用一个汉字的视觉空间,并使用 2 个字节存储。后来,其中的一些全角字符因为比较有用,就得到了广泛应用(比如全角的逗号「,」、问号「?」、感叹号「!」、空格「 」等),专用于中日韩文本,成为了标准的中日韩标点字符。而其它的许多全角符号失去了价值,因为我们现在很少需要让纯文本的中文和西文字字对齐了,就很少再用了。

另外需要说明的是:现在全球文本编码的事实标准是 UTF-8 等基于 Unicode 字符集的编码格式。Unicode 吸纳了许多遗留字符,并且为了兼容性而保留了所有字符。所以这些没什么用的全角字符也留下来了。而国家标准也仍在要求字体和软件支持这些全角字符。

第一点大多数朋友都明白,也最直接,那就是使用全角和半角打出的字的形状是不一样的。

第二点是字符存储上的区别,在全角状态下,我们输入一个字母所占的字符是两个;而在半角状态下,我们输入一个字母所占的字符只有一个。输入汉字两者所占的字符都是两个。

半角输入:自由 之路 ddd
全角输入:自由 之路ddd

上面给出了一个列子,我们明显可以看出在全角和半角模式下,字母和空格等西文字符之间的区别,而中文字符则没区别。

其实有些字符编码相关知识的同学可以很清楚的看出:全角字符和半角字符在字符集中就是两个码点不同的字符,他们表示的含义相同,但是展示的效果有差异。这个差异要么体现在形状上,要么体现在字符宽度上。

https://www.zhihu.com/question/19605819/answer/12355856

全角字符和半角字符的区别主要体现在以下几个方面:

  • 宽度:全角字符的宽度是半角字符的两倍。
  • 编码:全角字符使用两字节编码,而半角字符使用一字节编码。
  • 应用:全角字符通常用于表示汉字、日文假名、韩文谚文,以及一些特殊符号,而半角字符通常用于表示英文字母、数字、以及一些特殊符号。

全角字符和半角字符在不同的场合有不同的使用要求。例如,在中文输入法中,通常使用全角字符来输入汉字,而使用半角字符来输入英文字母和数字。在一些编程语言中,全角字符和半角字符也有不同的含义。

base64编码

Base64 是一种编码方式,最早出现在电子邮件传输协议中。电子邮件问世之初,传递消息时只支持 ASCII 字符,后来随着电子邮件的广泛使用,传递非ASCII字符内容的需求增加,例如:传输中文、传输文件(图片、视频)。

为解决这一问题,最好的方案是在不改变传输协议的基础上,做一种扩展方案来支持非ASCII内容传输,把非 ASCII 字符用ASCII来表示,Base64编码应运而生。

Base64的编码原理

Base64的原理比较简单,每当我们使用Base64时都会先定义一个类似这样的数组:

['A', 'B', 'C', ... 'a', 'b', 'c', ... '0', '1', ... '+', '/']

上面就是Base64的索引表,字符选用了"A-Z、a-z、0-9、+、/" 一共64个可打印字符,这是标准的Base64协议规定。

在日常使用中我们还会看到"="或"=="号出现在Base64的编码结果中,"="在此是作为填充字符出现,后面会讲到。

Base64编码的目标是将任何二进制数据编码为纯文本,其基本原理是将三个字节的二进制数据编码为四个字符。