有趣生活

当前位置:首页>科技>彻底理解字符编码5K字深入理解字符编码模型

彻底理解字符编码5K字深入理解字符编码模型

发布时间:2026-07-21阅读(1)

导读前言最近踩坑了后端的文档生成,本想写篇相关的实践总结,忽然感悟到电子文档的魅力,尤其以“字符编码模型”为最,特此进行研究并写下此文。不了解Unicode、U....前言

最近踩坑了后端的文档生成,本想写篇相关的实践总结,忽然感悟到电子文档的魅力,尤其以“字符编码模型”为最,特此进行研究并写下此文。

不了解Unicode、UTF-8、UTF-16、GBK,搞不清楚码位、码元等概念,或者经常遇到乱码问题的小伙伴都可以在本文找到答案。

简述字符编码

相信大家一定对上面的场景不陌生(„ಡωಡ„),这是一个经典的字符编码错误导致的乱码问题。而解决的方法也很简单,在打开文件的时候指定正确的编码方式即可。如图中的文本文件 a.txt 采用 utf-8 编码,指定该编码方式打开并读取文本内容如下图。

解决方案很简单,但方案背后所蕴含的知识可不简单,这就是“字符编码”。众所周知,一个字符类型(char)长度为 1 字节,由多个 char 组成的数组(约定以 \0 结尾)就是字符串。问题来了,一个字节只能表示 2828 (256)个数字,如何表示百倍于它的汉字呢?上面用到的 utf-8 又是什么?为什么不指定它就会乱码呢?

想要表示汉字很简单,一个字节不够,那再来个字节呀。用多个字节表示字符,又涉及具体用几个字节、如何高效利用空间、要表示范围足够大同时灵活可拓展等问题,因此提出了以 utf-8 为代表的字符编码的方法来告诉计算机如何解析字节流并将其转化为字符流。由于大部分字符编码的方法不互相兼容,用与编码时不同的编码方案解析它自然就会出错或者解析成错误的内容。

下面给出维基百科中的定义:字符编码(英语:Character encoding)是把字符集中的字符编码为指定集合中某一对象(例如:比特模式、自然数序列、8位组或者电脉冲),以便文本在计算机中存储和通过通信网络的传递。

概念可能不够具体,狭义来说,字符编码就是将字符(包括英文字母、汉字等)编码为计算机可以存储与解析的字节流形式,同时也支持从字节流解析回字符的形式。这是对现实生活中用到的文字与符号的建模,将它们用一种计算机可以理解的方式表示,来方便计算机处理。

为了标准化字符编码的过程,人们对编码设计的过程进行划分,提出了字符编码的抽象架构模型,共有 5 层,分别解决了字符编码流程中的五个具体细节问题,接下来进行详细介绍。

字符编码模型

设计字符编码,根据先后顺序可以分为以下五个步骤:

  1. 定义字符集:解决包含的字符范围的问题,声明都有哪些字符
  2. 编码字符集:解决如何用数字信号唯一的表示字符集中的每个字符
  3. 设计计算机保存字符编码用哪种数据类型以哪种规则保存:解决如何用某种数据类型描述字符编码后的数字信号
  4. 确定保存字符编码所用的数据类型如何映射到字节序列:解决数据类型(用来描述字符编码的数字信号)在计算机中(用字节序列)的表示方法
  5. 选择传输时合适的字节序列编码与压缩方案:解决描述字符串的字节序列在传输过程中的编码与压缩问题

基于上述五个步骤,定义:

字符编码模型=抽象字符表 编码字符集(CCS) 字符编码表(CEF) 字符编码方案(CES) 传输编码语法字符编码模型=抽象字符表 编码字符集(CCS) 字符编码表(CEF) 字符编码方案(CES) 传输编码语法

五层模型1. 抽象字符表(Abstract character repertoire)

抽象字符表定义了当前的字符编码所支持的所有抽象字符的集合。

抽象字符是指人从视觉上认为不同而从含义逻辑上认为相同的一组实际字符的集合,可认为该集合中的字符表示的含义相同。一层含义是,一个汉字有楷、行、草、隶等多种形体,但都表示同一个汉字,如下图。另一层含义是,在 Unicode 中西班牙语的 ñ 由 n 和 ~ 两个字符组成,虽然看上去是一个,但是两种不同的含义。

抽象字符表有些标准是封闭性的,抽象字符集合不会改变(包括: ASCII、ISO 8859 系列等);有些标准是开放性的,可以不断将新的字符添加到标准中(比如:Unicode)。

2. 编码字符集(CCS: Coded Character Set)

编码字符集在第一层抽象字符集的基础上,为每一个字符分配一个唯一的数字编码,让抽象的字符通过数字的方式表示出来。

编码字符集是一个映射过程,将抽象字符集中的每一个字符一对一地映射到一个坐标(若是一维就是单个整数)上,而每一个映射到的坐标(也就是数字编码)称为码位(也称码点),每个字符所占的码位称为码位值。所以,也可以称:编码字符集就是把抽象字符集中的每个抽象字符映射为码位值

用来表示码位的坐标空间的维度称之为编码空间,可用一组数字、存储单元尺寸或者一些特殊形式表示。例如:GB 2312 汉字编码空间可表示为 94 × 94;ISO-8859-1的编码空间可表示为 8 比特或 256;Unicode 采用行、列、面的三维描述表示码位值。

这里特别讲解一下 Unicode(统一码)的编码字符集。每个 Unicode 字符编码可以表示为:U 6个十六进制数字,比如:0 表示为 \U000030。Unicode 采用平面 16-bit 编码方式,每个平面的编码空间为 2^16(用\U000030的后四位表示,使用两个字节),共 17 个平面(用\U000030的前两位表示,使用一个字节),理论上能表示的字符数 = 平面数(17) × 平面编码空间大小(2^16) = 1114112。17个平面编号为0-16(0x00-0x10),如下图。

日常中常用的字符都定义在 0 号平面,该平面的码点表示时可以省略前两个十六进制位的平面号。平面中不是每个位置都定义了对应的字符,还有不少空间保留或作特殊用途。

每个抽象字符在 Unicode 中采用唯一且不可变的字符名称来表示,如:拉丁字母 K 在 Unicode 中的字符名称是“Latin Capital Letter K”,码点是 004B。

3. 字符编码表(CEF: Character Encoding Form)

字符编码表将数字表示的码位值转换为整型值序列(由多个固定有限长度的整形数据类型组成)表示。

用来表示码位的有限长度整形,是计算机表达字符编码(码位值)的单位,称为编码单元,简称码元

定义字符编码表有两步:

  1. 定义码元
  2. 定义如何使用多个码元表示码点值的规则

定义码元通常采用 8 bit(字节)的倍数。码元的存在,规整了表示不同字符的存储方式,避免在一串字符中用各种长度的整形混合表示。在计算机中采用字节的倍数存储与处理也匹配其存储、传输和处理的单位,对应计算机中的数据类型。

定义用码元表示码位值的规则,分为定长编码和变长编码。定长编码就是自身到自身的映射,如 ASCII 的编码 0-127,对应 7 bit,直接用 1 字节表示。UTF-32是 Unicode 对应的定长编码方案,字节内容一一对应码点。

变长编码基于某种规则将码位值根据需要映射到不同个数的码元序列上。

UTF-8

此处以 Unicode 最通用的字符编码表 UTF-8 进行说明。UTF-8 是 Unicode 的一种边长编码,码元为 8 bit,采用 1 - 4 个码元(字节)表示一个字符,根据字符码位值的不同变换表示长度。编码规则如下:

Copyright © 2024 有趣生活 All Rights Reserve吉ICP备19000289号-5 TXT地图HTML地图XML地图