背景

前两天在网上看到一篇关于编码的讨论,仔细学习了一下unicode,utf8,utf16的定义。这篇博客旨在让读者真正理解他们是什么。

什么是编码

在阅读本文之前建议读者先去阅读这篇文章:http://www.freebuf.com/articles/others-articles/25623.html,如果你没有耐心读完他也没关系,只需要明白三个道理:

1,这个世界上从来没有纯文本这回事,如果你想读出一个字符串,你必须知道它的编码。如果你不知道一段数据流的编码方式,你就永远不会知道这里面的内容。

2,Unicode是一个简单的标准,用来把字符映射到数字上。Unicode协会的人会帮你处理所有幕后的问题,包括为新字符指定编码。我们用的所有字符都在unicode里面有对应的映射,每个映射称为一个码点(http://en.wikipedia.org/wiki/Code_point

3,Unicode并不告诉你字符是怎么编码成字节的。这是被编码方案决定的,通过UTF来指定。

读完前面这篇文章之后你也许就了解了一个二进制流到屏幕字符的过程:

二进制流->根据编码方式解码出码点->根据unicode码点解释出字符->系统渲染绘出这个字符

文本字符保存到计算机上的过程:

输入字符->根据字符找到对应码点->根据编码方式把码点编码成二进制流->保存二进制流到硬盘上

从这个过程我们可以知道能不能从二进制流读取出字符关键就在于能不能找到二进制流的编码,掌握了编码方式的信息就可以用对应的逆过程解码。

看到这里有读者一定会问:为什么要编码,根据二进制流计算码点不好吗?

原因是良好设计的编码可以为我们提供很多附加的功能,包括容错纠错(在网络通信中尤其重要),自同步(不必从文本头部开始就可以解码)等等。编码从信息论的角度上来说就是增加了冗余的信息,冗余的这部分信息就可以为我们提供额外的功能。

utf8的编码规则

我们来看utf8和utf16具体是如何编码的:

Utf8有如下特点:

1.可变长编码,由第一个字节决定该字符编码长度

2.向下兼容ascii码(这也是为什么用utf8编码可以完美打开ascii文本文件)

Utf8的编码规则:

  1. 一个字节的编码完全用于ascii码(从0-127)
  2. 大于127的码点都用多字节来编码,多字节包含开头字节和后续字节

开头字节以若干个1开头(长度为几就有几个1,因此只要读完开头字节就可以知道本字符共有多少个字节),后接1个0.后续字节都以10开头

  1. 从右到做,后续字节每个字节占用原码点6个位,剩余的放在开头字节。
  2. 开头字节和后续字节不共享任何数据,因此utf8是自同步的。举例来说我们看到一个字节以110…开头时,我们就知道这是一个2字节的字符的开头字节。

具体来举几个例子:

字符 码点 二进制 UTF-8 16进制 UTF-8
$ U+0024 0100100 00100100 24
¢ U+00A2 000 10100010 11000010 10100010 C2 A2
U+20AC 00100000 10101100 11100010 10000010 10101100 E2 82 AC

你真的理解编码吗?unicode,utf8,utf16详解的更多相关文章

  1. 关于编码:Unicode/UTF-8/UTF-16/UTF-32

    关于编码,绕不开下面这些概念 ①Unicode/UTF-8/UTF-16/UTF-32 ②大小端字节序(big-endian/little-endian) ③BOM(Byte Order Mark) ...

  2. 细说:Unicode, UTF-8, UTF-16, UTF-32, UCS-2, UCS-4

    1. Unicode与ISO 10646 全世界很多个国家都在为自己的文字编码,并且互不想通,不同的语言字符编码值相同却代表不同的符号(例如:韩文编码EUC-KR中“한국어”的编码值正好是汉字编码GB ...

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

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

  4. Unicode(UTF-8, UTF-16)令人混淆的概念

    为啥需要Unicode 我们知道计算机其实挺笨的,它只认识0101这样的字符串,当然了我们看这样的01串时肯定会比较头晕的,所以很多时候为了描述简单都用十进制,十六进制,八进制表示.实际上都是等价的, ...

  5. (转) Unicode(UTF-8, UTF-16)令人混淆的概念

    原文地址:http://www.cnblogs.com/kingcat/archive/2012/10/16/2726334.html 为啥需要Unicode 我们知道计算机其实挺笨的,它只认识010 ...

  6. Unicode(UTF-8, UTF-16)令人混淆的概念(转)

    文章转自http://www.cnblogs.com/kingcat/archive/2012/10/16/2726334.html (http://swiftlet.net/archives/cat ...

  7. Unicode(UTF-8, UTF-16)令人混淆的概念----我看完了 不错

    来自:http://www.cnblogs.com/kingcat/archive/2012/10/16/2726334.html ---------------------------------- ...

  8. 【转】Unicode(UTF-8, UTF-16)令人混淆的概念

    参考地址:http://www.cnblogs.com/kingcat/archive/2012/10/16/2726334.html Java中,char类型用UTF-16编码描述一个代码单元 为啥 ...

  9. Unicode UTF-8 UTF-16的关系

    以下仅为个人学习的记录,如有疏漏不妥之处,还请不吝赐教. 关系 Unicode是一个字符集.顾名思义,字符的集合.GBK,BIG5,ISO8859-1,ASCII都是字符集. 有一点不同的是,Unic ...

随机推荐

  1. Lombok自定义annotation扩展含Intellij插件

    Lombok简介 Lombok(https://projectlombok.org/)  提供了以注解的形式为java对象增加属性和方法,这使得原来冗长的java源文件变的简洁(不需要再使用ide去生 ...

  2. 控制uniFrame显示的一个管理类

    控制uniFrame显示的一个管理类 (2016-03-29 06:41:17) 转载▼ 标签: delphi 分类: uniGUI 利用uniGUI Frame的机制来搭建项目,是非常好的实现方式, ...

  3. 在Delphi中处理word文档与数据库的互联

    在Delphi中处理word文档与数据库的互联 ---- 目前,Delphi被越来越多的人选中作为MIS系统开发中的前台工具.在以Delphi为前台,一些大型数据库为后台的MIS系统中,图形的处理不可 ...

  4. Android-Retrofit-2.0-Post与Get-请求有道词典翻译

    Retrofit-2.0版本后,内置已经集成了OKHttp,在使用Retrofit的时候 看似是Retrofit去网络请求的 实际上Retrofit只是封装,所以不要以为Retrofit是网络请求框架 ...

  5. @requestParamore与@pathvariable的区别

    http://localhost:8080/Springmvc/user/page.do?pageSize=3&pageNow=2 你可以把这地址分开理解,其中问号前半部分:http://lo ...

  6. Django:全文检索功能可参考博客

    https://blog.csdn.net/AC_hell/article/details/52875927 https://www.zmrenwu.com/courses/django-blog-t ...

  7. MS SQL的某一数据库成了Single User模式

    数据库恢复失败,原来的数据却变成了 当尝试打开数据库的属性,即出现上面图片异常的信息. 正常来说,是可以打开数据库的属性 此刻,你可以运行SQL语句来解决: USE master; GO ALTER ...

  8. C++获取系统信息(IP地址、硬件信息等)

    #include<stdio.h> #include<winsock2.h> //该头文件需在windows.h之前 #include<windows.h> #in ...

  9. flask的变量和函数

    flask 中有内置的的变量函数 ,那些特殊的变量可以实现某些功能 config :可以从模板中直接访问Flask当前的config对象:{{config.SQLALCHEMY_DATABASE_UR ...

  10. python 跨平台获取网卡信息和本机ip地址

    笔者在项目中遇到过获取本机网卡ip的例子,利用python库psutil解决了此问题. def get_netcard(): """获取网卡名称和ip地址 "& ...