当前位置: 首页 > news >正文

编码,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是磁盘启动的引导程序&#xff0c;其概括起来就是代码的搬运工&#xff0c;将代码搬到合适的位置。下图是对搬运过程的概括&#xff0c;可以有个印象&#xff0c;后面将详细讲解。 bootsect.s主要做了如下的三件事: 搬…...

django组件552

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…...

【枚举算法的Java实现及其应用】

文章目录 枚举算法概述枚举算法的实现步骤Java实现枚举算法枚举算法的底层工作原理枚举算法的底层代码讲解枚举算法的实际应用场景枚举算法在场景中解决的问题总结 枚举算法概述 枚举算法是一种通过列举所有可能情况来解决问题的方法。这种算法在解决一些特定类型的问题时非常…...

linux led 驱动

前言 今天是儿童节&#xff0c;挣个奖牌给小孩玩玩。 在 linux 驱动大家庭中&#xff0c;LED 驱动算是个儿童&#xff0c;今天就写写他吧。正好之前写过他的婴儿时期《i.MX6ULL 裸机点亮 LED》&#xff0c;记得那时候他还穿着开裆裤呢&#xff0c;裸鸡嘛。 ioremap() 裸机程…...

平面最近点对(分治算法)

文章目录 平面最近点对&#xff08;分治算法&#xff09;Solution流程完整模板代码 平面最近点对&#xff08;分治算法&#xff09; 文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 平面最近点对&#xff08;加强版&#xff09; - 洛谷 给你一些点&#xff0c;求两点之…...

【基于前后端分离的博客系统】Servlet版本

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一. 项目简介 1. 项目背景 2. 项目用到的技…...

在线Excel绝配:SpreadJS 16.1.1+GcExcel 6.1.1 Crack

前端&#xff1a;SpreadJS 16.1.1 后端&#xff1a; GcExcel 6.1.1 全能 SpreadJS 16.1.1此版本的产品中包含以下功能和增强功能。 添加了各种输入掩码样式选项。 添加了在保护工作表时设置密码以及在取消保护时验证密码的支持。 增强了组合图以将其显示为仪表图。 添加了…...

一个轻量的登录鉴权工具Sa-Token 集成SpringBoot简要步骤

Sa-Token 集成SpringBoot简要步骤 1.1 简单介绍 Sa-Token是一个轻量级Java权限认证框架。 主要解决的问题如下&#xff1a; 登录认证 权限认证 单点登录 OAuth2.0 分布式Session会话 微服务网关鉴权等一系列权限相关问题。 1.2 登录认证 设计思路 对于一些登录之后…...

day 44 完全背包:518. 零钱兑换 II;377. 组合总和 Ⅳ

完全背包&#xff1a;物品可以使用多次 完全背包1. 与01背包区别 518. 零钱兑换 II1. dp数组以及下标名义2. 递归公式3. dp数组如何初始化4. 遍历顺序:不能颠倒两个for循环顺序5. 代码 377. 组合总和 Ⅳ:与零钱兑换类似&#xff0c;但是是求组合数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可以独立完成工作&#xff0c;但现今许多应用程序需要响应外部请求。例如&#xff0c;在微服务的情况…...

牛客网DAY2(编程题)

圣诞节来啦&#xff01;请用CSS给你的朋友们制作一颗圣诞树吧~这颗圣诞树描述起来是这样的&#xff1a; 1. "topbranch"是圣诞树的上枝叶&#xff0c;该上枝叶仅通过边框属性、左浮动、左外边距即可实现。边框的属性依次是&#xff1a;宽度为100px、是直线、颜色为gr…...

Java经典笔试题—day14

Java经典笔试题—day14 &#x1f50e;选择题&#x1f50e;编程题&#x1f36d;计算日期到天数转换&#x1f36d;幸运的袋子 &#x1f50e;结尾 &#x1f50e;选择题 (1)定义学生、教师和课程的关系模式 S (S#,Sn,Sd,Dc,SA &#xff09;&#xff08;其属性分别为学号、姓名、所…...

一个帮助写autoprefixer配置的网站

前端需要用到postcss的工具&#xff0c;用到一个插件叫autoprefixer&#xff0c;这个插件能够给css属性加上前缀&#xff0c;进行一些兼容的工作。 如何安装之类的问题在csdn上搜一下都能找到&#xff08;注意&#xff0c;vite是包含postcss的&#xff0c;不用在项目中安装pos…...

C语言中的类型转换

C语言中的类型转换 隐式类型转换 整型提升 概念&#xff1a; C语言的整型算术运算总是至少以缺省&#xff08;默认&#xff09;整型类型的精度来进行的为了获得这个精度&#xff0c;表达式中字符和短整型操作数在使用之前被转换为普通整型&#xff0c;这种转换成为整型提升 如…...

String底层详解(包括字符串常量池)

String a “abc”; &#xff0c;说一下这个过程会创建什么&#xff0c;放在哪里&#xff1f; JVM会使用常量池来管理字符串直接量。在执行这句话时&#xff0c;JVM会先检查常量池中是否已经存有"abc"&#xff0c;若没有则将"abc"存入常量池&#xff0c;否…...

C++ 里面lambda和函数指针的转换

问题说明 原始问题&#xff0c;代码如下会编译报错&#xff1a; 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插件快速入门

前言 现代前端对速度的追求已经进入二进制工具时代&#xff0c;Rust 开发成为每个人的必修课。 一般我们将常见的前端 Rust 开发分为以下几类&#xff0c;难度由上至下递增&#xff1a; 开发 wasm 。 开发 swc 插件。 开发代码处理工具。 我们将默认读者具备最简单的 Rus…...

【C++ 学习 ⑧】- STL 简介

目录 一、什么是 STL&#xff1f; 二、STL 的版本 三、STL 的 6 大组件和 13 个头文件 四、学习 STL 的 3 个境界 五、STL 的缺陷 参考资料&#xff1a; STL教程&#xff1a;C STL快速入门&#xff08;非常详细&#xff09; (biancheng.net)。 C STL是什么&#xff0c;有…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

力扣热题100 k个一组反转链表题解

题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...