ASCII码

使用一个字节(8位),对128个字符进行编码;

最高位始终为0;

码数范围为0000_0000(0x00)0111_1111(0x7F)

Unicode

开始的编码设计

使用两个字节(16位),对65536个字符进行编码;

范围为0000_0000_0000_0000(0x0000)1111_1111_1111_1111(0xFFFF)

0x0000 - 0x007F对应的字符,与ASCII码保持一致;

最终的编码设计

由于世界上的字符,超过了65536个,所以开始只用两个字节的设计已经不足够了,需要扩展;

最终扩展如下:

  • 基本多语言平面(BMP, Basic Multilingual Plane)

    和开始的设计一致,用两个字节来编码,码数范围0x0000 - 0xFFFF

    但是,在这个范围里,有预留0xD800 - 0xDFFF的码数,他们不代表任何字符,仅用于作为增补平面的代理对而存在;

  • 增补平面(SP, Supplementary Plane)

    超出BMP所能表示的字符,改用如下范围:0x10000 - 0x10FFFF来编码;

    Unicode编者认为这个范围已经足够全世界的字符编码了,因为这足够表示一百万多个字符了;

代理对(surrogate pair)

预留的0xD800 - 0xDFFF,分为两部分:

  • 高位0xD800 - 0xDBFF
  • 低位0xDC00 - 0xDFFF

这样做的目的,是为了UTF-16编码方式;

一个高位加一个低位,共四个字节,定义了SP中的字符的UTF-16编码;

码点(code point)

Unicode编码中,一个字符所对应的码数,称为该字符的码点;

通常在计算机的字符和字符串中,使用\u码点的形式来转义码点,来表示一个Unicode编码的码点所对应的字符;

UTF-16

请注意,Unicode编码的码点,是人为约定的对字符的编码方式;

但是计算机只认二进制,所以如何将Unicode定义的字符的码点,编码为计算机实际存储的二进制串,以及如何从一串二进制串,解码成Unicode定义的字符的码点,就是UTF-16要做的事情;

UTF-16的16代表最小的编码单位是16位二进制串;

编码

分为两种情况:

  • BMP中的字符

    直接用Unicode定义的码点作为UTF-16编码即可;

  • SP中的字符

    使用两个16位二进制串进行编码,即采用四个字节来编码;

    现在假设有一个字符,其Unicode定义的码点为0xAAAAA,对其进行如下操作:

    • u = 0xAAAAA - 0x10000;
    • 将u写成二进制串:yyyy_yyyy_yyxx_xxxx_xxxx
    • 则该字符的UTF-16编码为:1101_10yy_yyyy_yyyy 1101_11xx_xxxx_xxxx

    SP的UTF-16编码的两个16位二进制串:

    第一个16位串的前六位固定是1101_10,结合yy的范围(00 - 11),即1101_1000 - 1101_1011,此范围即是代理对的高位的前两位0xD8 - 0xDB

    第二个16位串的前六位固定是1101_11,结合xx的范围00 - 11,即1101_1100 - 1101_1111,此范围即是代理对的低位的前两位的范围0xDC - 0xDF

    再结合各自后面八位二进制串的范围0000_0000 - 1111_1111,就可以得到各自完整的代理对;

    也就是说,SP的UTF-16的编码结果,即为高位+低位的四个字节的代理对;

解码

只要看一个16位二进制串的头八位,是否在代理对的范围即可;

  • 不在代理对的范围

    说明是BMP中的字符,直接对应Unicode码点找到对应的字符即可;

  • 在代理对的范围

    说明是SP中的字符,再根据头六位确定好代理对的高低位,

    去除各自的前六位,组成20位二进制串,再加上0x10000即为Unicode定义的码点,即可找到对应的字符;

UTF-8

UTF-8是不同于UTF-16的另一种对Unicode的编解码方式;

不同之处就在于,UTF-8的8代表最小的编码单位是8位二进制串;

编码

UTF-8对码点的编码方式如下:

  • 码点范围0x0000 - 0x007F

    UTF-8编码为二进制串0xxx_xxxx,与ASCII码保持一致,长度为1个字节;

  • 码点范围0x0080 - 0x07FF

    UTF-8编码为二进制串110x_xxxx 10xx_xxxx,长度为2个字节;

  • 码点范围0x0800 - 0xFFFF

    UTF-8编码为二进制串1110_xxxx 10xx_xxxx 10xx_xxxx,长度为3个字节;

  • 码点范围0x10000 - 0x10FFFF

    UTF-8编码为二进制串1111_0xxx 10xx_xxxx 10xx_xxxx 10xx_xxxx,长度为4个字节;

假设现在有一个字符,码点在范围0x0800 - 0xFFFF中:

  • 将其码点写成二进制串:xxxx_yyyy yyzz_zzzz
  • 则UTF-8编码的第一个字节为1110_xxxx;
  • 第二个字节为10yy_yyyy
  • 第三个字节为10zz_zzzz

解码

只要看第一个字节的首位即可:

  • 首位为0

    说明在码点范围0x0000 - 0x007F,直接对应Unicode码点找到对应的字符即可;

  • 首位为1,再看从首位开始,遇到第一个0结束,一共有几个1

    • 两个1,说明UTF-8编码长度为2个字节
    • 三个1,说明UTF-8编码长度为3个字节
    • 四个1,说明UTF-8编码长度为4个字节
    • 去除对应字节的固定位,组合为一个二进制串,找到对应Unicode码点的字符即可;

代码单元(code unit)

不同的UTF编码,所对应的编码单位的长度不同;

UTF-16的编码单位的长度为16位二进制;

UTF-8的编码单位的长度为8位二进制;

这个编码单位称为代码单元;

比如对于UTF-16的编码:

BMP中,一个字符所对应的UTF-16的16位二进制串,称为该字符的代码单元;

而在SP中,一个字符所对应的UTF-16的两个16位二进制串,称为该字符的一对代码单元;

而对于UTF-8的编码:

在码点范围0x0000 - 0x007F中,一个字符所对应的UTF-8的4个字节,称为该字符的4个代码单元;

在码点范围0x0080 - 0x07FF中,一个字符所对应的UTF-8的4个字节,称为该字符的4个代码单元;

在码点范围0x0800 - 0xFFFF中,一个字符所对应的UTF-8的4个字节,称为该字符的4个代码单元;

在码点范围0x10000 - 0x10FFFF中,一个字符所对应的UTF-8的4个字节,称为该字符的4个代码单元;

也就是说,随着UTF编码形式的不同,同一个字符的码点,会有不同个数的代码单元;

字符编码:Unicode & UTF-16 & UTF-8的更多相关文章

  1. 字符编码-UNICODE,GBK,UTF-8区别【转转】

    字符编码介绍及不同编码区别 今天看到这篇关于字符编码的文章,抑制不住喜悦(总结的好详细)所以转到这里来.转自:祥龙之子http://www.cnblogs.com/cy163/archive/2007 ...

  2. 彻底搞懂字符编码(unicode,mbcs,utf-8,utf-16,utf-32,big endian,little endian...)[转]

    最近有一些朋友常问我一些乱码的问题,和他们交流过程中,发现这个编码的相关知识还真是杂乱不堪,不少人对一些知识理解似乎也有些偏差,网上百度, google的内容,也有不少以讹传讹,根本就是错误的(例如说 ...

  3. java字符编码-Unicode编码问题刨根究底

    博客搬家: java字符编码问题 前段时间在读<java核心技术卷一>,遇到一些名词:码点.代码单元等,其实字面意思不难理解,解释如下 码点(code point):Unicode编码表中 ...

  4. 字符编码unicode,utf-8和ascii

    Ascii编码 由于计算机是美国人发明的,因此,最早只有127个字符被编码到计算机里,也就是大小写英文字母.数字和一些符号,这个编码表被称为ASCII编码,比如大写字母A的编码是65,小写字母z的编码 ...

  5. 字符串和字符编码unicode

    python基础第三天 字符串 str 作用: 用来记录文本(文字)信息,给人类识别用的,为人们提供注释解释说明 表示方式: 在非注释中,凡是用引号括起来的部分都是字符串 ' 单引号 " 双 ...

  6. 一句话理解字符编码(Unicode ,UTF8,UTF16)

    Unicode和ASCII码属于同一级别的,都是字符集,字符集规定从1到这个字符集的最大范围每个序号都各表示什么意思.比如ASCII字符集中序号65表示"A". 那接下来的UTF8 ...

  7. 字符编码-Unicode、Utf-8 笔记

    Unicode 将世界上所有的符号都纳入其中.每一个符号都给予一个独一无二的编码,那么乱码问题就会消失.这就是 Unicode,就像它的名字都表示的,这是一种所有符号的编码 UTF-8 UTF-8 就 ...

  8. Java 字符编码(一)Unicode 字符编码

    Java 字符编码(一)Unicode 字符编码 Unicode(http://www.unicode.org/versions/#TUS_Latest_Version) 是一个编码方案,说白了希望给 ...

  9. 001. Java内存中的字符编码

    Java内存中的字符编码 Unicode字符集及utf-8 .utf-16.utf-32 等字符编码方式 字符集:字符表示的数字集合,元素称为码点或码位: 字符编码:字符实际的储存表示: 码点:一个码 ...

  10. Python编程笔记(第二篇)二进制、字符编码、数据类型

    一.二进制 bin() 在python中可以用bin()内置函数获取一个十进制的数的二进制 计算机容量单位 8bit = 1 bytes 字节,最小的存储单位,1bytes缩写为1B 1KB = 10 ...

随机推荐

  1. 知识图谱实体对齐2:基于GNN嵌入的方法

    知识图谱实体对齐2:基于GNN嵌入的方法 1 导引 我们在上一篇博客<知识图谱实体对齐1:基于平移(translation)嵌入的方法>中介绍了如何对基于平移嵌入+对齐损失来完成知识图谱中 ...

  2. rowkey设计原则和方法

    rowkey设计首先应当遵循三大原则: 1.rowkey长度原则 rowkey是一个二进制码流,可以为任意字符串,最大长度为64kb,实际应用中一般为10-100bytes,它以byte[]形式保存, ...

  3. Maven中POM文件总体配置说明

    POM文件总体配置说明 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://w ...

  4. Vue学习之--------全局事件总线(2022/8/22)

    文章目录 1.全局事件总线基础知识(GlobalEventBus) 2.图解过程 3.代码实例 3.1 main.js 3.1 App.vue 3.2 School.vue 3.3 Student.v ...

  5. 齐博x1关于小程序个性源代码的说明

    系统默认推荐商家小程序使用通用型的源码,即框架套壳iframe形式的.这个灵活性更高.但如果有特殊需求的话,也可以设置个性源码,比如配合uni-app使用,针对不同的小程序就使用不同的uni-app风 ...

  6. AR人体姿态识别,实现无边界的人机交互

    近年来,AR不断发展,作为一种增强现实技术,给用户带来了虚拟和现实世界的融合体验.但用户已经不满足于单纯地将某件虚拟物品放在现实场景中来感受AR技术,更想用身体姿势来触发某个指令,达到更具真实感的人机 ...

  7. 乾象投资:基于JuiceFS 构建云上量化投研平台

    背景 乾象投资 Metabit Trading 成立于2018年,是一家以人工智能为核心的科技型量化投资公司.核心成员毕业于 Stanford.CMU.清北等高校.目前,管理规模已突破 30 亿元人民 ...

  8. 谷歌拼音输入法扩展API开发指南

    为了帮助开发者在谷歌拼音输入法的基本输入功能基础上,开发和定义更丰富的扩展输入功能,谷歌拼音输入法提供了以Lua脚本编程语言为基础的输入法扩展API.利用输入法扩展API,开发者可以编写自定义的输入功 ...

  9. 第2-1-5章 docker安装MinIO实现文件存储服务-springboot整合minio-minio全网最全的资料

    目录 1. MinIO介绍 2. MinIO应用场景 2.1 单主机单硬盘模式 2.2 单主机多硬盘模式 2.3 多主机多硬盘分布式 3. MinIO特点 4. 存储机制 5. docker安装Min ...

  10. Java学习之Filter与Listener

    0x00前言 web中的Filiter:当客户端访问服务端资源的时候,过率器可以把请求拦截下来,完成一些特殊的功能 完成的操作一般都是通用的作用:列如登录验证. web中的Listener一般用于加载 ...