编码含义

关于编码的含义,之前也说过,计算机只能存储二进制序列
所以对于字符,保存的时候,需要进行编码为二进制,进行存储
呈现的时候,需要将二进制进行解码,转换成字符的形式
 
有很多种编码方式,比如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. BZOJ 3864

    dp of dp 我就是来贴个代码 #include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a ...

  2. PHP CURL获取页面内容输出例子

    使用PHP curl获取页面内容或提交数据,有时候希望返回的内容作为变量储存,而不是直接输出.这个时候就必需设置curl的CURLOPT_RETURNTRANSFER选项为1或true. 1.curl ...

  3. soapUI启动报错:The JVM could not be started. The maximum heap size (-Xmx) might be too large or an antivirus or firewall tool could block the execution.

    版本: soapUI-5.2.1 问题: 启动soapUI时报错:The JVM could not be started. The maximum heap size (-Xmx) might be ...

  4. ios开发中的深拷贝和浅拷贝

    这是一个老生常谈的话题,面试中也经常被问到,下面总结一下自己的一些心得. 一句话总结: 浅拷贝就是指针拷贝: 深拷贝是对象本身的拷贝: 下面一张抽象的图可以直观的表述出两句话的内涵 其实这里还引申出了 ...

  5. JDK各个版本的新特性

    对于很多刚接触java语言的初学者来说,要了解一门语言,最好的方式就是要能从基础的版本进行了解,升级的过程,以及升级的新特性,这样才能循序渐进的学好一门语言.今天先为大家介绍一下JDK1.5版本到JD ...

  6. HTML入门14

    HTML表单 这块部分开始强调表单也是用的比较多的部分,好好补漏啊啊啊啊 表单用来做交互,处理所有方面结构到样式,到自定义小部件. form元素,严禁嵌套表单,表单嵌套会使得表单得行为不可预知,引入f ...

  7. SpringMvc 中的实用工具类介绍(包括 ResponseEntity、 RestTemplate、WebUtils 等)

    此部分内容将包含 ResponseEntity. RestTemplate.WebUtils 等 1. ResponseEntity ① Sprring Mvc 中作为方法的返回值使用法 @Reque ...

  8. 替换url中的域名

    /**     *      * @param domain 域名     * @param port   端口号     * @param url    url路径     * @return   ...

  9. 基于Jmeter的thrift-RPC接口测试

    根据需求,产品部分功能采用thrift-RPC协议进行接口的增.删.改.查,前期采用Junit对其进行测试,为了提高RPC接口测试的简洁化和后期的性能测试需求,打算通过Jmeter的java类测试实现 ...

  10. .NET程序员所需要注意的网站资源

    一个程序员 需要 对 技术 和 行业 两方面同时具有极大热情和注意力才能让自己在一个新的台阶. 有些程序员是对技术有着极大的热情但是行业完全不注意,这样我感觉只能成为一个专家,并不能让自己真正的质变, ...