字符编码:Unicode & UTF-16 & UTF-8
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 - 0x007FUTF-8编码为二进制串
0xxx_xxxx,与ASCII码保持一致,长度为1个字节;码点范围
0x0080 - 0x07FFUTF-8编码为二进制串
110x_xxxx 10xx_xxxx,长度为2个字节;码点范围
0x0800 - 0xFFFFUTF-8编码为二进制串
1110_xxxx 10xx_xxxx 10xx_xxxx,长度为3个字节;码点范围
0x10000 - 0x10FFFFUTF-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的更多相关文章
- 字符编码-UNICODE,GBK,UTF-8区别【转转】
字符编码介绍及不同编码区别 今天看到这篇关于字符编码的文章,抑制不住喜悦(总结的好详细)所以转到这里来.转自:祥龙之子http://www.cnblogs.com/cy163/archive/2007 ...
- 彻底搞懂字符编码(unicode,mbcs,utf-8,utf-16,utf-32,big endian,little endian...)[转]
最近有一些朋友常问我一些乱码的问题,和他们交流过程中,发现这个编码的相关知识还真是杂乱不堪,不少人对一些知识理解似乎也有些偏差,网上百度, google的内容,也有不少以讹传讹,根本就是错误的(例如说 ...
- java字符编码-Unicode编码问题刨根究底
博客搬家: java字符编码问题 前段时间在读<java核心技术卷一>,遇到一些名词:码点.代码单元等,其实字面意思不难理解,解释如下 码点(code point):Unicode编码表中 ...
- 字符编码unicode,utf-8和ascii
Ascii编码 由于计算机是美国人发明的,因此,最早只有127个字符被编码到计算机里,也就是大小写英文字母.数字和一些符号,这个编码表被称为ASCII编码,比如大写字母A的编码是65,小写字母z的编码 ...
- 字符串和字符编码unicode
python基础第三天 字符串 str 作用: 用来记录文本(文字)信息,给人类识别用的,为人们提供注释解释说明 表示方式: 在非注释中,凡是用引号括起来的部分都是字符串 ' 单引号 " 双 ...
- 一句话理解字符编码(Unicode ,UTF8,UTF16)
Unicode和ASCII码属于同一级别的,都是字符集,字符集规定从1到这个字符集的最大范围每个序号都各表示什么意思.比如ASCII字符集中序号65表示"A". 那接下来的UTF8 ...
- 字符编码-Unicode、Utf-8 笔记
Unicode 将世界上所有的符号都纳入其中.每一个符号都给予一个独一无二的编码,那么乱码问题就会消失.这就是 Unicode,就像它的名字都表示的,这是一种所有符号的编码 UTF-8 UTF-8 就 ...
- Java 字符编码(一)Unicode 字符编码
Java 字符编码(一)Unicode 字符编码 Unicode(http://www.unicode.org/versions/#TUS_Latest_Version) 是一个编码方案,说白了希望给 ...
- 001. Java内存中的字符编码
Java内存中的字符编码 Unicode字符集及utf-8 .utf-16.utf-32 等字符编码方式 字符集:字符表示的数字集合,元素称为码点或码位: 字符编码:字符实际的储存表示: 码点:一个码 ...
- Python编程笔记(第二篇)二进制、字符编码、数据类型
一.二进制 bin() 在python中可以用bin()内置函数获取一个十进制的数的二进制 计算机容量单位 8bit = 1 bytes 字节,最小的存储单位,1bytes缩写为1B 1KB = 10 ...
随机推荐
- this硬绑定
一.this显示绑定 this显示绑定,顾名思义,它有别于this的隐式绑定,而隐式绑定必须要求一个对象内部包含一个指向某个函数的属性(或者某个对象或者上下文包含一个函数调用位置),并通过这个属性间接 ...
- 程序员便于开发的一些工具、网站、App。
http://www.kancloud.cn 关于文档,各种技术,框架的学习指南,API文档搜索方便. https://leetcode.com/ 程序员刷题面试网站,无聊的时候可以做一做.
- Filter 筛选器(三)之 自定义一个启动事务的 TransactionScopeFilter
如果一个方法内有多个写入操作,比如 写入A表,然后用A表的自增id 去写入B表,假如A表写入成功,但B表因为某种原因写入失败!(这就导致A表写入了脏数据) 这时候 我们可以自定义 一个Filter 进 ...
- hadoop集群配置全过程
一.nat配置1.虚拟机->编辑->虚拟网络编辑器->更改设置->移除原VMnet8->加新的VMnet8->点击NAT模式 桥接模式->NAT模式,初始化一 ...
- Dytechlab Cup 2022 (A - C)
Dytechlab Cup 2022 (A - C) A - Ela Sorting Books 分析:贪心,将字符串每一位都存在map里,从前往后尽量让每一个\(n / k\)的段\(mex\)值尽 ...
- 网页计时访问器application对象
网页计时访问器 application对象代表Web应用本身,整个Web共享一个application对象.开始于服务器打开结束与服务器关闭.在不同的浏览器打开j计时器仍然有作用.除非把服务器关闭 & ...
- 齐博x1 万能fun 调用任意数据表 任意字段就是这么任性调用
列举了几个常用的查询进行简单封装,虽然系统也有内置的但是很多人不大会就二次封装简化了一下. 这里只封装了一个条件 多个条件的自己再封装或者用标签解决比较好 这里只是说fun可以万能调用 1获取任意表的 ...
- $_SERVER["REQUEST_URI"],在 PHP 众多预定义服务器变量中,$_SERVER["REQUEST_URI"] 算是经常用到的,但是这个变量只有 apache 才支持
例如访问:http://localhost/index.php?app=lunbo获取到的$_SERVER["REQUEST_URI"]为"/index.php?app= ...
- 浅入浅出 1.7和1.8的 HashMap
前言 HashMap 是我们最最最常用的东西了,它就是我们在大学中学习数据结构的时候,学到的哈希表这种数据结构.面试中,HashMap 的问题也是常客,现在卷到必须答出来了,是必须会的知识. 我在学习 ...
- EntityFramework介绍
首先我们说明一下ORM是什么. 微软官方提供的ORM工具,ORM让开发人员节省数据库访问的代码时间,将更多的时间放到业务逻辑层代码上.开发人员使用Linq语言,对数据库操作如同操作Object对象 一 ...