编码,Part 1:ASCII、汉字及 Unicode 标准
个人博客
编码的历史由来就懒得介绍了,只需要知道人类处理文本信息是以字符为基本单位,而计算机在最底层只认识 0/1,所以当计算机要为人类存储/呈现字符时,就需要有一个规则,在字符和 0/1 序列之间建立映射关系,这就是编码规则。
因为计算机技术起源于欧美,所以最早的字符编码标准自然而然是基于英语制定的,英语最大的特点是它仅由 26 个大小写字母组合而成,再加上一些特殊字符,就构成了英语的文本世界,其基本字符的总数不会超过 128 个,鉴于 7 个比特位可以有 128 种 0/1 组合,所以用 7 个比特位就足以应付所有需要编码的字符,这样最早的统一标准就诞生了,称为 ASCII(American Standard Code for Information Interchange,美国信息交换标准码)码。在 Linux 系统中输入 man ascii,可以得到如下 ascii 码表:

 以字符 ‘a’ 为例,16 进制编码为 61,对应的 10 机制表示就是 97,对应的二进制表示为 0110 0001。但西方世界也不是只有英语字母,于是从 1987 年开始,ISO 基于 8 比特位制定了 ISO-8859 系列编码标准,系列中的每一个标准用到的编码位数都不超过 8 位。

按 ascii 和 ISO-8859 编码标准的规定,其包含的字符都可以用一个字节(8 比特)表示,在存储时也就只占用一个字节,但世界上并不只有西方文字,还有很多其他类型。
最典型就是中文,中文是典型的象形文字,而且是世界上使用人数最多的文字,常用汉字数量就不止 1000 个,指望 ascii 是不行的——就算把存 ascii 码的 8 个比特全用来表示中文,也不够,所以也发展出了自己的一套编码规范:
- 1980 年,中国搞了自己的编码方案 GB/T 2312(GB/T 代表推荐性国家标准,可以参考前一篇 博文 里的介绍),一般简称 GB2312。
- 1993 年,国际标准化组织 ISO 制定了编码标准 ISO/IEC 10646-1:1993,国内予以承认,并编号为 GB 13000.1-1993。
- 1995 年,国内基于 GB2312 扩展了一套编码方案 GBK(汉字内码扩展规范),并收录了 GB13000.1 和 Big5(由台湾资讯工业策进会在1984 年制定)中的汉字,微软在 Windows 95、Windows NT 3.51 中进行了实现,称为 Code Page 936。
- 2000 年,制定了国标 GB 18030-2000,目前已作废。
- 2005 年,制定了国标 GB 18030-2005,为现行的 GB18030 标准。
- 2022 年,制定了国标 GB 18030-2022,将在 2023年8月1日生效。
GB2312、GBK、GB18030 就是目前老系统中常用的三种中文编码方案。
这还只是中文,当我们把眼界放大到整个地球(球外暂不考虑),仅仅东亚就还有日文、韩文,还有中亚、中东、非洲等等国家和地区的文字都需要编码进计算机。如此多的国家和地区,如此多的语言文字,再各自搞一套就真乱成一锅粥了,除了 ASCII 被默认继承,同一个或两个字节,在不同的编码标准中基本就代表着不同的字符,必须要找到正确的标准才能进行解码,在计算机互通的情况下,这变得很复杂。一套统一的、国际化的编码标准势在必行,尤其对于跨国公司开展全球化业务,所以 Unicode 的诞生可以说是名正言顺。
第一版 Unicode 早在 1991 年就发布了,目前已发展到第 15 版。

 在早期的 ASCII 编码标准中,因为一个 8 位的字节就可以表示完字符集中所有的字符,而字节也正是计算机中进行运算、存储的基本单元(如 8 位是传统的加法器、锁存器、数据选择器的输入/输出),所以编码、运算、存储时没什么可争议的。但当被编码的字符数量超过了一个字节可以有的组合数时,就变得有趣了。
举个例子,假设我现在有 257 个字符需要编码到同一个编码标准中,由于 8 位最多只有 256 种组合(0-255),对于第 257 个字符,至少要再加 1 位,达到 9 位,才能给这个多出来的字符一个唯一编码(如 1 0000 0000),但我们是用数字来对字符进行编码的,在计算机中表示数字的基本单元是 8 位的字节(不存在 9 位的基本单元),也就是说,要想在计算机里进行处理,必须把第 257 个字符呈现为 2 个字节(如 0000 0001 0000 0000)。以此类推,当我需要表示出第 65536 个字符时,在计算机里至少需要 3 个字节,如果字符数量继续增加,就得按这个逻辑继续增加字节数。
从举的例子来看,计算机中的字符编码虽然比实际编码多了一些比特位,因为只是高位补 0,两者的值还是一致的,实际使用中则没有这么简单。
让我们再次回到例子中,现在我有 257 个字符,第 257 个字符的十进制编码值是 256,在计算机中至少要用两个字节表示 —— 0000 0001 0000 0000。现在我要表示(十进制编码值是 1 的)第 2 个字符,在计算机中既可以用 1 个字节表示—— 0000 0001,也可以用 2 个字节表示 —— 0000 0000 0000 0001。那么,是用 1 个字节,还是 2 个字节?
如果用 2 个字节,每个字符编码时所用的字节数就是一样的,便于寻址,代价是对资源的浪费。如果内存、存储成本昂贵,则固定 2 字节的方案就值得商榷。
如果用 1 个字节,就存在两种情况,有的字符用 1 个字节表示,有的字符(必须)用 2 个字节表示,字符对应的字节数不固定,这时就需要在第 1 个字节中告诉计算机,读到当前字节就可以开始解码,还是要再读取 1 个字节,用 2 个字节来解码。需要表示这个信息,可以基于固有的大小属性进行表示,也可以添加额外的位来表示。
可以看到,编码值和在计算机中的实际编码所要表达的含义具有差别(前者目的是做符号的唯一数字标识,后者还要考虑计算机本身的限制),因为 Unicode 要收录所有的字符到同一个编码标准中,必然存在超过一个字节的情况,所以分得很清楚,前者被称为 Code Point,后者被称为 Code Units,在前面介绍的几种编码标准(ASCII、GB2312、GBK、GB18030、Big5)中,每一种标准的 Code Point 和 Code Units 都是确定的。但在 Unicode 中,只规定了 Code Points,没有规定 Code Units,当我们说 Unicode 时,说的只是一套统一的字符集和它对应的 Code Points(U+0000 ~ U+10FFFF),并不包含在计算机中实际是怎么编码表示的。只有当说 UTF-8、UTF-16、UTF-32 时,才表示在使用 Unicode 字符集的基础上,在计算机中字符具体的 Code Units 是怎样的。三种方案的差别就在于 Code Units 的大小,实际使用中根据需要进行选择。
简单看一下 UTF-8 中对 Code Units 是如何规定的。

 UTF-8 中所有字符的 Code Units 长度并不一致:
- 1 字节,第一个字节的高 1 位为 0,兼容 ASCII;
- 2 字节,第一个字节的高 2 位为 1,第 3 位为 0;
- 3 字节,第一个字节的高 3 位为 1,第 4 位为 0;
- 4 字节,第一个字节的高 4 位为 1,第 5 位为 0。
而在 UTF-16 中,字符有 2 字节、4 字节两种长度;在 UTF-32 中,所有字符都用 4 字节。
以 ‘蛤’ 为例,在 Unicode 中的 Code Point 是 U+86E4,在 UTF-8、UTF-16(有大小端之分)、UTF-32(有大小端之分)下的表示分别是:
- UTF-8:E8 9B A4(11101000 10011011 10100100,把背景高亮部分抽出来就是 10000110 11100100,也就是 16 进制的 86 E4)
- UTF-16BE:86 E4
- UTF-32BE:00 00 86 E4
相关文章:
 
编码,Part 1:ASCII、汉字及 Unicode 标准
个人博客 编码的历史由来就懒得介绍了,只需要知道人类处理文本信息是以字符为基本单位,而计算机在最底层只认识 0/1,所以当计算机要为人类存储/呈现字符时,就需要有一个规则,在字符和 0/1 序列之间建立映射关系&#…...
C++ Eigen库矩阵操作
C Eigen库 序号功能例子1赋值Eigen::MatrixXf mat (12,1); \\% mat << 1, 2, 3, 4,5,6,7,8,9,10,11,12;2Inplace操作 \\% resizemat.resize(4, 3); \\% 1 5 9 \\% 2 6 10 \\% 3 7 11 \\% 4 8 123转置 \\% transposeInPlacemat.transposeInPlace(); \\% 1 2 3 4 \\% 5…...
 
Linux-0.11 boot目录bootsect.s详解
Linux-0.11 boot目录bootsect.s详解 模块简介 bootsect.s是磁盘启动的引导程序,其概括起来就是代码的搬运工,将代码搬到合适的位置。下图是对搬运过程的概括,可以有个印象,后面将详细讲解。 bootsect.s主要做了如下的三件事: 搬…...
 
django组件552
前言:相信看到这篇文章的小伙伴都或多或少有一些编程基础,懂得一些linux的基本命令了吧,本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python:一种编程语言&…...
【枚举算法的Java实现及其应用】
文章目录 枚举算法概述枚举算法的实现步骤Java实现枚举算法枚举算法的底层工作原理枚举算法的底层代码讲解枚举算法的实际应用场景枚举算法在场景中解决的问题总结 枚举算法概述 枚举算法是一种通过列举所有可能情况来解决问题的方法。这种算法在解决一些特定类型的问题时非常…...
 
linux led 驱动
前言 今天是儿童节,挣个奖牌给小孩玩玩。 在 linux 驱动大家庭中,LED 驱动算是个儿童,今天就写写他吧。正好之前写过他的婴儿时期《i.MX6ULL 裸机点亮 LED》,记得那时候他还穿着开裆裤呢,裸鸡嘛。 ioremap() 裸机程…...
平面最近点对(分治算法)
文章目录 平面最近点对(分治算法)Solution流程完整模板代码 平面最近点对(分治算法) 文章首发于我的个人博客:欢迎大佬们来逛逛 平面最近点对(加强版) - 洛谷 给你一些点,求两点之…...
 
【基于前后端分离的博客系统】Servlet版本
🎉🎉🎉点进来你就是我的人了博主主页:🙈🙈🙈戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔🤺🤺🤺 目录 一. 项目简介 1. 项目背景 2. 项目用到的技…...
 
在线Excel绝配:SpreadJS 16.1.1+GcExcel 6.1.1 Crack
前端:SpreadJS 16.1.1 后端: GcExcel 6.1.1 全能 SpreadJS 16.1.1此版本的产品中包含以下功能和增强功能。 添加了各种输入掩码样式选项。 添加了在保护工作表时设置密码以及在取消保护时验证密码的支持。 增强了组合图以将其显示为仪表图。 添加了…...
一个轻量的登录鉴权工具Sa-Token 集成SpringBoot简要步骤
Sa-Token 集成SpringBoot简要步骤 1.1 简单介绍 Sa-Token是一个轻量级Java权限认证框架。 主要解决的问题如下: 登录认证 权限认证 单点登录 OAuth2.0 分布式Session会话 微服务网关鉴权等一系列权限相关问题。 1.2 登录认证 设计思路 对于一些登录之后…...
 
day 44 完全背包:518. 零钱兑换 II;377. 组合总和 Ⅳ
完全背包:物品可以使用多次 完全背包1. 与01背包区别 518. 零钱兑换 II1. dp数组以及下标名义2. 递归公式3. dp数组如何初始化4. 遍历顺序:不能颠倒两个for循环顺序5. 代码 377. 组合总和 Ⅳ:与零钱兑换类似,但是是求组合数1. dp数组以及下标名义2. 递归…...
 
K8s in Action 阅读笔记——【5】Services: enabling clients to discover and talk to pods
K8s in Action 阅读笔记——【5】Services: enabling clients to discover and talk to pods 你已了解Pod以及如何通过ReplicaSets等资源部署它们以确保持续运行。虽然某些Pod可以独立完成工作,但现今许多应用程序需要响应外部请求。例如,在微服务的情况…...
 
牛客网DAY2(编程题)
圣诞节来啦!请用CSS给你的朋友们制作一颗圣诞树吧~这颗圣诞树描述起来是这样的: 1. "topbranch"是圣诞树的上枝叶,该上枝叶仅通过边框属性、左浮动、左外边距即可实现。边框的属性依次是:宽度为100px、是直线、颜色为gr…...
 
Java经典笔试题—day14
Java经典笔试题—day14 🔎选择题🔎编程题🍭计算日期到天数转换🍭幸运的袋子 🔎结尾 🔎选择题 (1)定义学生、教师和课程的关系模式 S (S#,Sn,Sd,Dc,SA )(其属性分别为学号、姓名、所…...
 
一个帮助写autoprefixer配置的网站
前端需要用到postcss的工具,用到一个插件叫autoprefixer,这个插件能够给css属性加上前缀,进行一些兼容的工作。 如何安装之类的问题在csdn上搜一下都能找到(注意,vite是包含postcss的,不用在项目中安装pos…...
 
C语言中的类型转换
C语言中的类型转换 隐式类型转换 整型提升 概念: C语言的整型算术运算总是至少以缺省(默认)整型类型的精度来进行的为了获得这个精度,表达式中字符和短整型操作数在使用之前被转换为普通整型,这种转换成为整型提升 如…...
String底层详解(包括字符串常量池)
String a “abc”; ,说一下这个过程会创建什么,放在哪里? JVM会使用常量池来管理字符串直接量。在执行这句话时,JVM会先检查常量池中是否已经存有"abc",若没有则将"abc"存入常量池,否…...
C++ 里面lambda和函数指针的转换
问题说明 原始问题,代码如下会编译报错: using DecisionFn bool(*)();class Decide { public:Decide(DecisionFn dec) : _dec{dec} {} private:DecisionFn _dec; };int main() {int x 5;Decide greaterThanThree{ [x](){ return x > 3; } };retur…...
前端Rust开发WebAssembly与Swc插件快速入门
前言 现代前端对速度的追求已经进入二进制工具时代,Rust 开发成为每个人的必修课。 一般我们将常见的前端 Rust 开发分为以下几类,难度由上至下递增: 开发 wasm 。 开发 swc 插件。 开发代码处理工具。 我们将默认读者具备最简单的 Rus…...
 
【C++ 学习 ⑧】- STL 简介
目录 一、什么是 STL? 二、STL 的版本 三、STL 的 6 大组件和 13 个头文件 四、学习 STL 的 3 个境界 五、STL 的缺陷 参考资料: STL教程:C STL快速入门(非常详细) (biancheng.net)。 C STL是什么,有…...
 
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
 
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
 
Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
 
【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...
Python爬虫实战:研究Restkit库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的有价值数据。如何高效地采集这些数据并将其应用于实际业务中,成为了许多企业和开发者关注的焦点。网络爬虫技术作为一种自动化的数据采集工具,可以帮助我们从网页中提取所需的信息。而 RESTful API …...
