首页 > 其他分享 >Unicode、UTF-8、UTF-16编码之间的区别和相同

Unicode、UTF-8、UTF-16编码之间的区别和相同

时间:2024-04-04 11:22:05浏览次数:21  
标签:编码 UTF 字节 字符 16 Unicode

转自:https://www.sohu.com/a/474232786_121124376

计算机起源于美国,上个世纪,他们对英语字符与二进制位之间的关系做了统一规定,并制定了一套字符编码规则,这套编码规则被称为ASCII编码

ASCII 编码一共定义了128个字符的编码规则,用七位二进制表示 ( 0x00 - 0x7F ), 这些字符组成的集合就叫做 ASCII 字符集

随着计算机的普及,在不同的地区和国家又出现了很多字符编码,比如: 大陆的 GB2312、港台的 BIG5, 日本的 Shift JIS等等

由于字符编码不同,计算机在不同国家之间的交流变得很困难,经常会出现乱码的问题,比如:对于同一个二进制数据,不同的编码会解析出不同的字符

当互联网迅猛发展,地域限制打破之后,人们迫切的希望有一种统一的规则, 对所有国家和地区的字符进行编码,于是 Unicode 就出现了

Unicode 简介

Unicode 是国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言、跨平台的文本信息转换

Unicode 字符集的编码范围是 0x0000 - 0x10FFFF, 可以容纳一百多万个字符, 每个字符都有一个独一无二的编码,也即每个字符都有一个二进制数值和它对应,这里的二进制数值也叫 码点, 比如:汉字 "中"的 码点是 0x4E2D, 大写字母 A的码点是 0x41, 具体字符对应的 Unicode 编码可以查询 Unicode字符编码表

字符集和字符编码

字符集是很多个字符的集合,例如 GB2312 是简体中文的字符集,它收录了六千多个常用的简体汉字及一些符号,数字,拼音等字符

字符编码是 字符集的一种实现方式,把字符集中的字符映射为特定的字节或字节序列,它是一种规则

比如:Unicode 只是字符集,UTF-8、UTF-16、UTF-32 才是真正的字符编码规则

Unicode 字符存储

Unicode 是一个符号集, 它只规定了每个符号的二进制值,但是符号具体如何存储它并没有规定

前面提到, Unicode 字符集的编码范围是 0x0000 - 0x10FFFF,因此需要 1 到 3 个字节来表示

那么,对于三个字节的 Unicode字符,计算机怎么知道它表示的是一个字符而不是三个字符呢 ?

如果所有字符都用三个字节表示,那么对于那些一个字节就能表示的字符来说,有两个字节是无意义的,对于存储来说,这是极大的浪费,假如 , 一个普通的文本, 大部分字符都只需一个字节就能表示,现在如果需要三个字节才能表示,文本的大小会大出三倍左右

因此,Unicode 出现了多种存储方式,常见的有 UTF-8、UTF-16、UTF-32,它们分别用不同的二进制格式来表示 Unicode 字符

UTF-8、UTF-16、UTF-32 中的 "UTF" 是 "Unicode Transformation Format" 的缩写,意思是"Unicode 转换格式",后面的数 字表明至少使用多少个比特位来存储字符, 比如:UTF-8 最少需要8个比特位也就是一个字节来存储,对应的, UTF-16 和 UTF-32 分别需要最少 2 个字节 和 4 个字节来存储

UTF-8 编码

UTF-8: 是一种变长字符编码,被定义为将码点编码为 1 至 4 个字节,具体取决于码点数值中有效二进制位的数量

UTF-8 的编码规则:

  1. 对于单字节的符号,字节的第一位设为 0 ,后面 7 位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的, 所以 UTF-8 能兼容 ASCII 编码,这也是互联网普遍采用 UTF-8 的原因之一
  1. 对于 n 字节的符号( n > 1 ),第一个字节的前 n 位都设为 1 ,第 n + 1 位设为 0 ,后面字节的前两位一律设为 10 。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码

下表是Unicode编码对应UTF-8需要的字节数量以及编码格式

Unicode编码范围(16进制)UTF-8编码方式(二进制)
000000 - 00007F 0xxxxxxx ASCII码
000080 - 0007FF 110xxxxx 10xxxxxx
000800 - 00FFFF 1110xxxx 10xxxxxx 10xxxxxx
01 0000 - 10 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

表格中第一列是Unicode编码的范围,第二列是对应UTF-8编码方式,其中红色的二进制 "1"和 "0"是固定的前缀, 字母 x表示可用编码的二进制位

根据上面表格,要解析 UTF-8 编码就很简单了,如果一个字节第一位是 0,则这个字节就是一个单独的字符,如果第一位是 1,则连续有多少个 1,就表示当前字符占用多少个字节

下面以 "中"字 为例来说明 UTF-8 的编码,具体的步骤如下图, 为了便于说明,图中左边加了 1,2,3,4 的步骤编号

首先查询 "中"字的 Unicode 码 0x4E2D, 转成二进制, 总共有 16 个二进制位, 具体如上图 步骤1 所示

通过前面的 Unicode 编码和 UTF-8 编码的表格知道,Unicode 码 0x4E2D对应 000800 - 00FFFF的范围,所以, "中"字的 UTF-8 编码 需要 3个字节,即格式是 1110xxxx 10xxxxxx 10xxxxxx

然后从 "中"字的最后一个二进制位开始,按照从后向前的顺序依次填入格式中的 x字符,多出的二进制补为 0, 具体如上图 步骤2、步骤3 所示

UTF-16 编码

UTF-16 也是一种变长字符编码, 这种编码方式比较特殊, 它将字符编码成 2 字节 或者 4 字节

具体的编码规则如下:

  1. 对于 Unicode 码小于 0x10000 的字符, 使用 2 个字节存储,并且是直接存储 Unicode 码,不用进行编码转换
  1. 大于 0x10FFFF 的 Unicode 码无法用 UTF-16 编码

下表是Unicode编码对应UTF-16编码格式

Unicode编码范围(16进制)具体Unicode码(二进制)UTF-16编码方式(二进制)字节
0000 0000 - 0000 FFFF xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx 2
0001 0000 - 0010 FFFF yy yyyyyyyy xx xxxxxxxx 110110yy yyyyyyyy 110111xx xxxxxxxx 4

表格中第一列是Unicode编码的范围,第二列是 具体Unicode码的二进制 ( 第二行的第二列表示的是 Unicode 码 减去 0x10000后的二进制 ) , 第三列是对应UTF-16编码方式,其中红色的二进制 "1"和 "0"是固定的前缀, 字母 x和 y表示可用编码的二进制位, 第四列表示 编码占用的字节数

前面提到过, "中"字的 Unicode 码是 4E2D, 它小于 0x10000,根据表格可知,它的 UTF-16 编码占两个字节,并且和 Unicode 码相同,所以 "中"字的 UTF-16 编码为 4E2D

我从 Unicode字符表网站 找了一个老的南阿拉伯字母, 它的 Unicode 码是: 0x10A6F, 可以访问 https://unicode-table.com/cn/10A6F/ 查看字符的说明, Unicode 码对应的字符如下图所示

下面以这个 老的南阿拉伯字母的 Unicode 码 0x10A6F为例来说明 UTF-16 4字节的编码,具体步骤如下,为了便于说明,图中左边加了 1,2,3,4 、5 的步骤编号

首先把 Unicode 码 0x10A6F转成二进制, 对应上图的 步骤 1

UTF-32 编码

UTF-32 是固定长度的编码,始终占用 4 个字节,足以容纳所有的 Unicode 字符,所以直接存储 Unicode 码即可,不需要任何编码转换。虽然浪费了空间,但提高了效率。

UTF-8、UTF-16、UTF-32 之间如何转换

前面介绍过,UTF-8、UTF-16、UTF-32 是 Unicode 码表示成不同的二进制格式的编码规则,同样,通过这三种编码的二进制表示,也能获得对应的 Unicode 码,有了字符的 Unicode 码,按照上面介绍的 UTF-8、UTF-16、UTF-32 的编码方法 就能转换成任一种编码了

后续还有内容,如大端编码(高位在前)、小端编码(高位在后)等内容,请参考上面的连接

标签:编码,UTF,字节,字符,16,Unicode
From: https://www.cnblogs.com/yeziwinone/p/18113992

相关文章

  • C++:递增递减运算符(16)
    递增递减就是自加1或者自减1,但是还有前置递增,后置递增,前置递减,后置递减,两者的区别也大有不同,接下来就去看一下过程a=1b=1b=++aa=2b=2a=1b=1b=a++a=2b=1a=2b=2b=--aa=1b=1a=2b=2b=a--a=1b=2递增前置递增#include<iostream>usingnamespacestd;intmain()......
  • P1164 小A点菜
    这种的动态规划题目主要还是不能被自己的思路限制了,之前的dp[i][j]是“最大值”;这里得把dp[i][j]理解为前i个物品放到j容的背包中的方法;那么很显然有递推公式:代码:#include<iostream>#include<vector>#include<algorithm>#include<math.h>#include<sstream>#include<stri......
  • "NU1605: 错误形式的警告: 检测到包降级"的解决办法
    这两行的意思是需要我们升级Maui.Controls的版本在8.0.14,取高版本。同理,再次进行:最后:......
  • HTML期末大作业~海贼王6页~Web大学生网页成品-s016
    HTML期末大作业~学生HTML个人网页作业作品下载个人主页博客网页设计制作大学生个人网站作业模板简单个人网页制作,HTML网页设计结课作业http://imianba.cn/#/articles?category=1&theme=0这段代码是HTML代码,它定义了一个名为“海贼王”的网站的结构。它包含一个头部(h......
  • PTA:7-116 点与圆的位置关系
    作者 zzz单位 重庆科技大学在平面直角坐标系中,给定一个圆的圆心坐标Ox,Oy以及半径R,再给定一个点的坐标Px,Py,请判断这个点与圆的位置关系。输入格式:先输入三个正整数,分别代表圆心的横纵坐标Ox,Oy和半径R。在输入两个正整数,分别代表给定点的横纵坐标Px,Py。输入的所有数......
  • BZOJ3160万径人踪灭-回文子序列(位置对称)计数
    link:https://www.luogu.com.cn/problem/P4199写manacher看到的(其实重点并不在manacher)题意:给一个仅包含2种字母的字符串,问有多少种不同的子序列,满足:内容和位置都是对称的不能是连续的一段\(1\leqn\leq10^5\)答案=子序列个数-回文串个数,回文串用manacher跑,子序列则考虑......
  • 0基础 三个月掌握C语言(16)
    ⽂件操作为什么使⽤⽂件?如果没有⽂件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失了,等再次运⾏程序,是看不到上次程序的数据的,如果要将数据进⾏持久化的保存,我们可以使⽤⽂件什么是⽂件?磁盘(硬盘)上的⽂件是⽂件。但是在程序设计中,我们⼀般谈......
  • 推荐几个好用的电商API接口(淘宝天猫丨京东1688商品详情数据接口)
    电商API接口主要用于帮助开发者将电商功能集成到自己的应用程序中,实现诸如商品检索、商品价格数据获取、订单处理、物流跟踪等功能。以下是一些常用的电商API接口提供商:一、主流电商平台API:淘宝开放平台:提供淘宝、天猫、1688等阿里巴巴集团旗下的电商平台接口,用于商品检索、......
  • 【STM32嵌入式系统设计与开发】——16InputCapture(输入捕获应用)
    这里写目录标题STM32资料包:百度网盘下载链接:链接:https://pan.baidu.com/s/1mWx9Asaipk-2z9HY17wYXQ?pwd=8888提取码:8888一、任务描述二、任务实施1、工程文件夹创建2、函数编辑(1)主函数编辑(2)USART1初始化函数(usart1_init())(3)USART数据发送函数(USART1_Send_Data())(4)USART......
  • 【建议收藏】阿里巴巴1688专业术语大全,电商运营必备
    PV:全称PageView,即页面访问量,每打开一次页面PV计数+1。UV:全称UniqueVisitor,指独立访客访问数,一台电脑终端为一个访客。SKU:SKU是指一款商品,每款都有一个SKU,便于电商品牌识别商品。一款商品多色,则是有多个SKU;例:一件衣服,有红色、白色、蓝色。GMV:交易金额。BSR:1688买家服务......