编码含义

关于编码的含义,之前也说过,计算机只能存储二进制序列
所以对于字符,保存的时候,需要进行编码为二进制,进行存储
呈现的时候,需要将二进制进行解码,转换成字符的形式
 
有很多种编码方式,比如ASCII
(American Standard Code for Information Interchange,美国信息交换标准代码)
使用一个字节进行编码,一个字节可以表示的最大值为255
很显然,对于英语和其他一些西欧语言来说,足够了,英文字母总共才几个对吧
 
那么对于汉字呢?ASCII显然是不够用的,所以出现了GBK等以支持汉字
那么,日语 韩语呢?他们当然也搞出来一些支持他们文字的编码

Unicode诞生

于是,人们意识到他们应该提出一种标准方案来展示世界上所有语言中的所有字符,出于这个目的,Unicode诞生了
Unicode 是一种字符集,规定了符号对应的二进制代码
至于这个二进制代码如何存储则没有任何规定,也就是说它是一种编码规定
是编码字符集,而不是实际的编码方案
 
最初Unicode使用一个16位长度的二进制序列,也就是最多支持   (2的16次方-1) 65536个字符,也就是0  ~ 65535
范围是 0x0000 ~0xFFFF 
Unicode使用U+前缀, 加上编码的值,来表示Unicode中的字符编码
也就是  U+0000   ~  U+FFFF 

Unicode不够用了

显然,随着更多字符的增加,  65536 是不够用的
于是Unicode 不得不进行扩展,于是使用8位用作扩展位,形式如下
一个字节8位可以表示 2的8次方-1 = 256 个数,最大可以扩展为 256 *65526=16777216 个
不过也不需要那么多的字符, 仅仅使用了前面的17个
也就是
00 01 02 03 04 05 06 07 08 0A 0B 0C 0D 0E 0F 10
 
于是按照扩展位,划分了17个维度,这每个维度,叫做一个平面
17个平面,编号从 0~16
每个平面 65536个字符
17个平面,扩展后总共可以表示1114112个字符
扩展后的范围为
U+000000   ~  U+10FFFF  
 
其中对于第一个U+00  也就是U+0000到U+FFFF ,包含了最常见的字符 
被称作 基本多语言平面  Basic Multilingual Plane, BMP
其余的U+010000   ~  U+10FFFF   被称作辅助平面
至此你应该了解到了,什么是Unicode的
他就是一个具有17个平面,每个平面可以容纳65536个字符的一张巨大的字符码表
一个字符对应一个二进制序列
基本平面中使用四位十六进制数 在零号平面以外的字符则需要使用五位或六位十六进制数了

编码方式

Unicode 没有规定字符对应的二进制码在计算机中如何存储,只是规定了他的值是多少而已
一个字符对应的实际的值,我们称之为代码点 code point
那么一个码点实际的值怎么存储呢?
可能需要1个,可能需要2个,甚至可能需要3个或者4个字节来表示
对于计算机来说,面对着一堆字节,他们知道到底哪个或者哪几个是一个字符呢?
听起来可能有点迷惑,不是知道具体的值了么?怎么还不知道如何表示?

比如数字1 他的码点是1
假如我用两个字节来存储,每个字节的前两位我当做其他的标志位, 设置为11
那么可能结果是这样子的11000000 11000001
显然,他的值并不是1
编码方式只是可以保证,你的字符是按照指定的字符集进行编码的
也就是说如果你告诉我拿出来码点为1 的,我会把1100 0000 1100 0001 解析成数字1
但是并不能保证我保存的数据就是他的码点的真值,0000 0001 ,中间形式是编码方式说了算的

最直观的例子就是网络中报文的传输,都会附加自己的头信息
所以中间传输的数据并不是跟你发送的数据一模一样,中间的数据就是编码形式的存储
但是,接收端接受解析后,就是跟你发送的数据一样的,这就好像是你的字符

 
 
存储的问题就是编码方式的问题,就是表示成什么形式的问题
编码方式有UTF-8 UTF-16  UTF-32
UTF-8 是变长
UTF-32 是定长
UTF-16介于他们之间 2个字节或者4个字节
 

utf-16

UTF-16编码以16位无符号整数为单位
我们把Unicode编码记作U  编码规则如下
如果U<0x010000, 也就是0x000000 ~ 0x00FFFF
U的UTF-16编码,  就是U对应的16位无符号整数
如果U≥0x010000    也就是0x010000 ~ 0x10FFFF
我们先计算下 U'=U-0x010000 
可以得出来 U'  范围是 0x000000 ~ 0x0FFFFF
显然,  U'的最大值为0xFFFFF   也就是最多20个1    也就是可以被写成20个二进制位
既然是20个二进制位,那么我们是不是可以把它拆分成两组呢?
每组10个二进制位    00  0000  0000
它能表示的范围是2的10次方=1024个

BMP是2个字节,16位, 很显然,如果把U' 拆分成两组,每组10个二进制位的话
每一个都能够保存到2个字节内

所以Unicode标准规定:基本多语言平面内,U+D800..U+DFFF的值不对应于任何字符,为代理区 ,其中又分为高代理区和低代理区

U+D800 加上10个二进制位的数值的最大值,可以得到高代理区的范围
U+D800 --->1101 10 00  0000  0000  + 0000 00 11  1111 1111 = 1101 1011 1111 1111 = 0xDBFF

下一个就是0xDBFF +1 = 0xDC00,所以低代理区从0xDC00  开始
0xDC00 加上10个二进制位的数值的最大值,可以得到低代理区的范围
0xDC00----> 1101  1100  0000  0000 + 0000 00 11  1111 1111 = 1101111111111111 = 0xDFFF

高代理区范围  U+D800 ~0xDBFF
低代理区范围   0xDC00 ~ 0xDFFF

代理区间是U+D800....U+DFFF

所以UTF-16的编码方式就是
先计算 U'=U-0x010000
然后将U'写成二进制形式:yyyy yyyy yyxx xxxx xxxx
然后分别计算高位代理和低位代理
U+D800 --->1101 10 00  0000  0000 +   0000 00 yy  yyyy yyyy = 1101 10 yy  yyyy  yyyy

0xDC00----> 1101  1100  0000  0000 + 0000 00 xx  xxxx  xxxx =  1101  11xx  xxxx  xxxx

再精简下步骤
1. 先计算 U'=U-0x010000
2. 然后将U'写成二进制形式:yyyy yyyy yyxx xxxx xxxx
3.两个值为   1101 10 yy  yyyy  yyyy  /    1101  11xx  xxxx  xxxx
 
在这种处理方式下
如果一旦读取到值为U+D800 ~0xDBFF  ,他必然是代理区间中的一部分,也就非 0号平面中的字符
而且,我们还能够根据值判断出来,到底是高位还是低位,也就是第一个还是第二个数值
只需要取出来这20位,然后再加上0x010000  这就是这个字符的码点
 
可以看得出来,对于基本平面中的字符,使用2个字节长度,16位表示,这被称之为一个代码单元
对于除了基本平面外的辅助平面,使用4个字节长度来表示,也就是两个代码单元
 
之前我们提到过,Unicode中的一个字符的值,被称之为一个码点
显然,一个码点,可能被一个代码单元存储,也可能被两个连续的代码单元存储

UTF-32

UTF-32编码以32位无符号整数为单位
Unicode的UTF-32编码就是其对应的32位无符号整数
32位可以表示的个数为  2的32次方  为4294967296,显然绰绰有余,没什么好说的了

UTF-8

UTF-8 是目前互联网上使用最广泛的一种 Unicode 编码方式,可变长
使用 1 - 4 个字节表示一个字符,根据字符的不同变换长度  
 
规则
可以把编码分解成两部分,head和body
head中记录需要字节的个数,使用第一个字节中1 的个数来表示
body记录真实的数据, 如果需要不止一个字节,那么body自然由多个字节组成,每个body的前两个字节为10  其余为数据

UTF-8编码的最大长度是4个字节,也就是最多有21个x 表示
Unicode的最大码位0x10FFFF   0001 0000 1111 1111 1111 1111也只有21位
如果一个字节足够表示
只需要一个字节即可表示,那么第一位为0  其余7位用于表示字符编码的值
看得出来明显的好处,可以兼容ASCII 
如果一个字节不够表示,根据范围选择,需要几个字节,就有几个1,然后补一个0   后面的body依次存放数据即可
想要确定一个码点的编码
1. 查看范围,根据上表确定格式
2.转换为对应的二进制序列
3. 替换掉x即可

字节序

根据我们上面描述的utf8 以及utf16都有可能使用不止一个字节进行编码
其实还有很多其他数据也不仅仅是一个字节进行表达
在计算机中最终都是二进制序列的形式
比如utf-16中,虽然我可以根据值确定是否在0号平面内,还是在扩展辅助平面的
但是,如何把一个二进制序列解析为他的值,这是一个问题
比如
0000 0001  0000 0010 假如说这是一个十六进制数
他到底表示的是0102 还是0201? 从哪边开始解读?
人会很自然的把左边当高位,右边当低位, 但是, 计算机, 你必须对他进行说明
这就是字节序的问题
其实就是高位和低位与内存地址高低的对应关系
分为大端排序( Big endian  BE)和小端排序(Little endian  LE)
 
大端排序----高地址存储低位  低地址存储高位
小端排序----高地址存储高位  低地址存储低位
在内存中0x01020304的存储方式
 
内存地址 4000 4001 4002 4003
BE           01     02     03     04
LE           04     03     02     01
 
其实只要记住,大小端说的都是低地址
大端就是低地址存储高位
小端就是低地址存储低位
 

[十]基础数据类型之Unicode编码简介的更多相关文章

  1. Java基础-二进制以及字符编码简介

    Java基础-二进制以及字符编码简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 想必计算机毕业的小伙伴或是从事IT的技术人员都知道数据存储都是以二进制的数字存储到硬盘的.从事开 ...

  2. 【C# 基础概念】Unicode编码详解

    Unicode定义:Unicode(统一码.万国码.单一码)是计算机科学领域里的一项业界标准,包括字符集.编码方案等.Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字 ...

  3. python基础数据类型补充以及编码的进阶

    一.基本数据类型的补充循环列表改变列表大小的问题#请把列表中索引为基数的元素写出l1=[1,2,3,4,5,6]for i in l1: if i%2!=0: print(i)结果:135二:基本数据 ...

  4. 基础数据类型之AbstractStringBuilder

    String内部是一个private final char value[]; 也就意味着每次调用的各种处理方法,返回的字符串都是一个新的,性能上,显然.... 所以,对于可变字符序列的需求是很明确的 ...

  5. Python基础编程:字符编码、数据类型、列表

    目录: python简介 字符编码介绍 数据类型 一.Python简介 Python的创始人为Guido van Rossum.1989年圣诞节期间,在阿姆斯特丹,Guido为了打发圣诞节的无趣,决心 ...

  6. Unicode/UTF-8/GBK/ASCII 编码简介

    转载:http://blog.csdn.net/u014785687/article/details/73928167 一.字符编码简介 1.ASCII编码 每一个ASCII码与一个8位(bit)二进 ...

  7. day02_20190106 基础数据类型 编码 运算符

    一.格式化输出 name = input('请输入姓名') age = input('请输入年龄') hobby = input('请输入爱好') job = input('请输入你的工作') # m ...

  8. 记录我的 python 学习历程-Day07 基础数据类型进阶 / 数据类型之间的转换 / 基础数据类型总结 / 编码的进阶

    基础数据类型 str(字符串) str:补充方法练习一遍就行 s.capitalize() 首字母大写,其余变小写 s = 'dyLAn' print(s.capitalize()) # Dylan ...

  9. python27期day07:基础数据类型补充、循环删除的坑、二次编码、作业题。

    1.求最大位数bit_length: a = 10 #8421 1010print(a.bit_length())结果:42.capitalize首字母变大写: s = "alex" ...

随机推荐

  1. json字符串的拼接

    关于json字符串的解析与拼接,第一次接触,留下个笔记了.......解析,是改的代码,拼接是纯的,解析就不说了,笔记一下拼接了 关于解析主要分三部分,一个是第一层处理,一个是第二层处理,一个是进行& ...

  2. On the Optimal Approach of Survivable Virtual Network Embedding in Virtualized SDN

    Introduction and related work 云数据中心对于虚拟技术是理想的创新地方. 可生存性虚拟网络映射(surviavable virtual network embedding ...

  3. vector的用法小结(待补全

    1.vector的好处 支!持!删!除! 节!省!内!存! 2.一点基础的小操作 ①插入操作:v.push_back(x) 在尾部插入元素x: ②删除操作 : v.erase(x)删除地址为x的元素 ...

  4. fiddler 应用

    一   pc 端抓取 例:本地调试代码,转换域名,请求网络数据 1:设置代理,以smart header 为例 ip为 127.0.0.1 端口与自己的fillder一致,注意将不代理的地址列表做修改 ...

  5. mac上配置react-native环境run-ios/run-android命令遇到的问题

    新报错(rn版本:0.53.3)2018.3.6 今天在搞react-native环境时,遇到了一些坑,这里记录一下. 首先最重要的一点是一定要按官网一步一步来,不然可能会出现一些奇奇怪怪的问题! 官 ...

  6. delegate异步

    using System; using System.Runtime.Remoting.Messaging; using System.Threading; using System.Threadin ...

  7. iview修改tabbar实现小程序自定义中间圆形导航栏及多页面登录功能

    emmm,用iview改了个自定义中间圆形的tabbar. 如下图所示, 重点,什么鬼是“多页面登录”? 例如:我现在要做一个功能,要说自己长得帅才能进去页面. 一个两个页面还好,但是我现在要每个页面 ...

  8. 怎么修改kodexplorer网盘下的版权

    前言: 要说kodexplorer,可是个好东西,在线web管理服务器文件,着实是网站管理员的好助手.内置的adminer管理数据库,用起来也是很顺手. 这么好的工具,还是免费的.但就是页面底部有ko ...

  9. ssh 报error: kex protocol error: type 30 seq 1

    由于近期服务器升级了openssl,在使用navicat连接数据库报 查看日志 sshd[1990]: error: kex protocol error: type 30 seq 1 [preaut ...

  10. Python基础之面向对象思维解决游戏《天龙八部》

    一.程序设计思维: 以面向对象的思维设计<天龙八部>游戏技能,使得技能效果在增加或者减少时,游戏技能整体框架不改变,仅仅增加或者减少技能效果 二.思路流程图如下: 三.变成框架实现代码: ...