我们知道ASCII码表中总共只有值在0-127之间的128个字符,用其表示纯粹的英文字符等已经足够了,而正是基于此产生了ANSI字符集。ANSI字符集中每个字符都是以一个8位的字节表示,但是后来随着全球信息化的加强,各国的语言都需要得到相应的体现,于是就出现了宽字符集,再后来就出现了unicode字符集,unicode又有UCS-2 和 UCS-4两种标准,不过通常unicode字符集中每个字符用两个字节来表示,这种表示方法就能囊括目前各国的语言字符,并且能有扩展的空间。而UTF8更是对传统的unicode等长字符表示方式的一种改进,它采用的较为灵活的变长方式,这样能够在概率上做到空间上的节省。下面是UTF8的原理说明。

UTF-8就是在互联网上使用最广的一种unicode的实现方式。其他实现方式还包括UTF-16和UTF-32,不过在互联网上基本不用。值得强调的是,UTF-8只是Unicode的实现方式之一。

UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

UTF-8的编码规则很简单,只有二条:

1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。

2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

下表总结了编码规则,字母x表示可用编码的位。

Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

当要表示的内容是 7位 的时候就用一个字节:0******* 第一个0为标志位,剩下的空间正好可以表示ASCII 0-127 的内容。

当要表示的内容在 8 到 11 位的时候就用两个字节:110***** 10****** 第一个字节的110和第二个字节的10为标志位。

当要表示的内容在 12 到 16 位的时候就用三个字节:1110***** 10****** 10****** 和上面一样,第一个字节的1110和第二、三个字节的10都是标志位,剩下的所有*的位置都应该根据实际数据加以填充有效数据。

以此类推:
四个字节:11110**** 10****** 10****** 10******
五个字节:111110*** 10****** 10****** 10****** 10******
六个字节:1111110** 10****** 10****** 10****** 10****** 10******

下面的参考文章出自http://blog.csdn.net/xiongchen/archive/2006/04/10/657068.aspx,我觉得总结的很好,尤其是这里有关于Surrogate Pair 的说明特粘贴至此:

一、        Unicode发展历史

字符必须经过编码以后才能被计算机处理,计算机使用的默认编码方式称为计算机的内码。早期的计算机使用7位的ASCII编码作为内码,但ASCII编码只能处理2^7=128个字符(包括英文字母、数字、符号、控制字符等),但是世界上有着成百上千种的语言,仅仅用ASCII是无法进行处理的。因此,世界各国开始纷纷研究处理本国语言的方法。在中国为了处理汉字,程序员设计了用于简体中文的GB2312编码和用于繁体中文的big5编码。

中国各种编码标准的情况:
1980年公布的GB2312编码标准一共收录了7445个字符,包括6763个汉字和682个其它符号。
GB2312 支持的汉字太少。1995年公布的汉字扩展规范GBK1.0则收录了21886个符号,它分为汉字区和图形符号区,汉字区包括21003个字符。2000年发布的GB18030正式取代GBK1.0成为国家标准,该标准收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字,所以现在的PC平台必须支持GB18030标准。

光是在中国就有那么多种不同的编码方式,世界各国编码方式的混乱情况就可想而知了。于是人们开始寻求一种统一的标准编码方法来表示和处理世界上绝大多的语言,众多的编码方法中最后只有Unicode编码最终成为了事实标准。

Unicode字符集编码是(Universal Multiple-Octet Coded Character Set) 通用多八位编码字符集的简称,支持世界上超过650种语言的国际字符集。它是由一个名为 Unicode 协会(Unicode Consortium)的机构制订的字符编码系统,支持现今世界各种不同语言的书面文本的交换、处理及显示。该编码于1990年开始研发,1994年正式公布,最新版本是2005年3月31日的Unicode 4.1.0,Unicode协会的官方网站是http://www.unicode.org,上面有关于Unicode的最新消息与最权威的资料。

二、        Unicode编码术语解释

UCS:Universal Multiple-Octet Coded Character Set(通用多八位编码字符集)的字符集,也可以以看作是"Unicode Character Set"的缩写。有UCS-2和UCS-4两种不同的实现方法,UCS-2采用两个字节进行编码,而UCS-4采用4个字节(实际上只用了31位,最高位必须为0)进行编码。

UTF编码:即UCS Transformation Format(UCS转换格式),它是将Unicode编码规则和计算机的实际编码对应起来的一个规则,用于网络传输、编码转换等。

Little Endian/Big Endian:字节序,也就是处理多字节时采用的顺序,例如:“南”字的Unicode编码是5357,字节序将决定它写到文件里时,是53在前还是57在前,如果是Big Endian则写为5357,反之则是5753。

三、        Unicode编码中的数学

1、 UCS-2使用2个字节,即16位来编码,所以共可以表示216=65536个码元;UCS-4使用4个字节,即32位来编码,但最高位必须为0,所以共可以表示231=2147483648个码元。

2、UCS-4码元的管理:由于UCS-4表示的码元非常大,所以需要采用一种机制来管理这些码元。UCS-4先根据最高字节不同分为27=128个群组,再根据第二个字节不同分为28=256个平面,然后根据第三个字节不同分为28=256行,最后根据第四个字节不同分为每行分为256个单元。也就是说同一行的不同单元只是最后一个字节不同,其余都相同。

3、UCS-4编码中,群号为0,平面号为0的所有码元称之为BMP,即Basic Multilingual Plane(基础多语言平面)。

4、将UCS-4的BMP去掉前面的两个零字节就得到了UCS-2。在UCS-2的两个字节前加上两个零字节,就得到了UCS-4的BMP。

这些数据和关系可以由下图清楚的得到:

群号: 0~127

平面号: 0~255

行号: 0~255

单元号: 0~255

0

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

UCS4-编码示意图

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

UCS-4 BMP编码示意图

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

UCS-2编码示意图

四、        Unicode编码的问题及解决方法

在Unicode里,所有的字符被一视同仁。像拆字、统计字数这些问题也就很容易解决。但是,也不可能在一夜之间所有的系统都使用Unicode来处理字符,所以Unicode从一开始,就必须考虑一个问题:和ASCII字符集之间的不兼容问题。比如字符“A”的ASCII码是65,而它的Unicode码则是0065,这就造成了一个非常大的问题:以前处理ASCII的那套机制不能被用来处理Unicode了。另一个更加严重的问题就是,C语言使用'/0'作为字符串结尾,而Unicode里恰恰有很多字符都有一个字节为0,这样一来,C语言的字符串函数将无法正常处理Unicode,除非把世界上所有用C写的程序以及他们所用的函数库全部换掉,这明显不可能做到。

事实证明,对可以用ASCII表示的字符使用UNICODE并不高效,因为UNICODE比ASCII占用大一倍的空间,而对ASCII来说高字节的0对他毫无用处。为了解决这个问题,就出现了一些介于ASCII和UNICODE中间格式的字符集,但他们本质也是UNICODE编码。他们被称为通用转换格式,即UTF(Universal Transformation Format)。它不像Unicode码一样只停留在理论基础上,它是真实地存在于计算机中的。

五、        UTF相关知识

目前存在的UFT系列编码标准有:UTF-7、UTF-7.5、UTF-8、UTF-16、UTF32五种,UTF-8和UTF16比较常用,下面分别介绍:

UTF-8:它是UNICODE的一种变长字符编码标准,现在已经标准化为RFC 3629。使用1到6个字节来编码UNICODE字符。UTF-8里英文字符仍然跟ASCII编码一样,因此原先的函数库可以继续使用。下面的表是它与Unicode编码之间的对应关系,接下来的算法也会用到。

Unicode

UTF-8

00000000 - 0000007F

0xxxxxxx

00000080 - 000007FF

110xxxxx 10xxxxxx

00000800 - 0000FFFF

1110xxxx 10xxxxxx 10xxxxxx

00010000 - 001FFFFF

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

00200000 - 03FFFFFF

111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

04000000 - 7FFFFFFF

1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

后面三个范围段里的Unicode编码,目前尚未使用到,所以一般不予考虑。这个表也称为字节模板,用于UTF-8与Unicode之间的转换.转换方法就是先确定编码所需要的字节数,然后用UNICODE编码二进制位从低位到高位依次填入上面表示为x的位上,不足的高位以0补充。举例说明:汉字“码”的Unicode编码十六进制为0x7801,落在第三个范围内,所以要用3个字节来表示,把0x7801转换为二进制111100000000001;按照字节模板写成:111 100000 000001的形式,然后用字节模板填充为:11100111 10100000 10000001,再转化为十六进制就得到了“码”的UTF-8编码为E7A081。这样以字节为编码单元,没有字节序的问题。

UTF-16:以16位为单元对Unicode进行编码。对于小于0x10000的UCS码,UTF-16编码就等于UCS码对应的16位无符号整数。对于≥ 0x10000的UCS码,定义了一个算法。不过由于实际使用的UCS2,或者UCS4的必然小于0x10000,所以就目前而言,可以认为UTF -16和UCS-2基本相同,如果不加特别说明,UTF-16基本上可以等同于Unicode和UCS-2。但UCS-2只是一个编码方案,UTF-16却要用于实际的传输,所以就不得不考虑字节序的问题,Unicode规范中推荐的标记字节顺序的方法是BOM(Byte Order Mark):字节序标识符。

在Unicode编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符"ZERO WIDTH NO-BREAK SPACE",而这个字符按照上述算法转换到UTF-8得到的是EF BB BF。这样如果接收者收到FEFF,就表明这个字节流是BigEndian的;如果收到FFFE,就表明这个字节流是LittleEndian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM,而如果接收到以EF BB BF开头的字节流,则说明这个字节流是用UTF-8来编码的。

2006-03-06补充关于代理对(Surrogate Pair)的相关内容:

为了发展,Unicode在BMP定义了一个代理区(Surrogate Zone)(D800至DFFF), 并将这个区域平分为前后两个各容纳1024(1K)个编码的区域(D800-DBFF及DC00-DFFF),分别称作高半代理(High Surrogate)及低半代理(Low Surrogate)区域。从这两个区域分别各取一个编码,分别称为高半代理键(High Surrogate Key)及低半代理键(Low Surrogate Key),由这两个Key组合成一个4字节代理对(Surrogate Pair)来表示一个编码字符。由于这两个区域内并没有定义任何的字符或符号,而且只有将这两个代理对(Surrogate Pair)结合在一起才能表示一个字符,单独使用其中的任何一个都没有意义。所以一个现有的应用程序无论何时遇到输入来自此两块保留区的任何一个编码时,它都是没意义的。

由Surrogate机制可对应到一百万个字符(1024x1024=1,048,576),这一百万个字符分别对应到ISO 10646 中00组的00至0F这16个字面(plane),每一个字面的容量为64K(256x256),CJK扩展集B,位于第二个字面(plane 2),第14, 15个字面(plane 15, 16)则留做用户自定义区域(user private area)。

关于更多字符编码等问题可以参阅《the unicode standard》等相关资料。

秒解UTF-8带来的烦恼相关推荐

  1. 3秒解一元二次不等式

    前言 这是我第一次在CSDN上发表文章,可能我学识尚浅,可能你会对我的文章内容的严谨性.准确性产生质疑.但我想说的是:我和你一样,满怀着对知识的热爱与渴求.在这里,我把自己闲暇时写的一些东西拿出来分享 ...

  2. 并联串联混合的电压和电流_用“串反并同”和“等效电源”秒解电压、电流、功率怎么变的问题...

    用"串反并同"和"等效电源"秒解电压.电流.功率怎么变的问题 小伙伴们,我终于忍不住要给大家讲一些秒解物理题的方法了,其实我本身并不喜欢"秒解&quo ...

  3. 香港高防服务器秒解是什么意思?

    在租用高防类服务器的时候,经常有服务商向用户推荐说,高防服务器能秒解攻击.那么,秒解到底是个怎样的概念?秒解的意思是,在服务器受到大流量攻击的时候,当攻击超过我们购买高防防御值的时候,会出现服务器IP ...

  4. 斗地主残局破解算法,斗地主残局暴力求解器算法,秒解各种斗地主残局

    斗地主残局破解,斗地主残局暴力求解器,秒解各种斗地主残局 秒解抖音.微信等各大平台的斗地主残局挑战 支持自定义出牌规则 输入双方的牌后单击"开始求解"按钮即可 求解完成后,电脑会自 ...

  5. 小米解bl锁跳过168小时_xiaomi redmi 红米秒解BL工具分享支持小米红米机型秒解BL跳过168小时

    目前小米的新机,官方风控都默认绑定7天也就是168小时才能解锁BL,部分账号需要绑定15天才能满足条件,导致很多爱玩机的小伙伴被拒门外.并不是所有人都愿意等待官方解锁时候,而跳过168小时解锁,也成为 ...

  6. 红米Note11/11Pro/11SE/11R秒解BL锁-跳168小时限制(RedNote 11 5G root 手机刷 magisk

    本教程采用Magisk注入boot的办法,适用于MIUI13,安卓版本12,其他版本未测试,请谨慎 之前在网上找了好久,也没找到能用的第三方rec,这手机也被阉割了谷歌服务,就算自行用安装器安装,也会 ...

  7. 【基础】秒解DP神器,你值得拥有

    如果想了解更多内容,欢迎关注我的微信公众号:信息学竞赛从入门到巅峰. 上期,我们讲解了解决动态规划的基本步骤,分别是:设置状态.枚举子问题,更新答案. 其实,这每一步都不是那么好做到的,需要有足够的经 ...

  8. 服务器稳定秒解是什么意思,高防秒解服务器特性以及如何实现秒解封

    在服务器,高防,租房的过程中,我们经常看到一个词"几秒钟解决服务器".这个怎么理解?服务器不是一个专业术语,而是一个描述高防和服务器特点的词汇在日常生活中,站长习惯于带服务器,的特 ...

  9. 详解7.0带来的新工具类:DiffUtil

    转: 详解7.0带来的新工具类:DiffUtil 一 概述 DiffUtil是support-v7:24.2.0中的新工具类,它用来比较两个数据集,寻找出旧数据集->新数据集的最小变化量. 说到 ...

最新文章

  1. 清华大学为何把突出贡献奖颁给他?看完这个我就懂了
  2. 腾讯云产业生态战略再升级,“4个100”与合作伙伴助力中小企业转型升级
  3. java数组实验报告_Java实验一实验报告
  4. POJ - 1459 Power Network(网络流-最大流)
  5. SAP UI5 setProperty 的执行逻辑单步调式和分析
  6. 11旋转编码器原理_旋转编码器的原理是什么?增量式编码器和绝对式编码器有什么区别?...
  7. 【OpenCV 例程200篇】50. 图像增强—直方图统计量图像增强
  8. android应用对于内存的大小是有限制的,Android 的内存限制
  9. toj 4319 盒子游戏
  10. postgre 生成数据库html文档_还在手动整理数据库文档?试试这个工具
  11. u-boot移植随笔:终于解决Nor Flash的问题了
  12. Java关键字volatile
  13. 使用phpqrcode来生成二维码/thinkphp
  14. 获得N^2个往返接力数字表格的算法
  15. 总结Cnblogs支持的常用Markdown语法
  16. win10便签常驻桌面_win7和win10自带桌面便签哪里找
  17. 电脑重装系统后如何删除微软商店下载记录
  18. centos 安装 谷歌BBR
  19. 基于VGG的图像多标签分类算法详解及实践
  20. 在JAVA中如何求Decimal的相反数,如何求Decimal的负数

热门文章

  1. 【Debug】安装labelme过程中出现的问题
  2. 21世纪最实用的智能营销软件是哪个
  3. 各种算法的时间复杂度
  4. java报错Error attempting to get column ‘XXX’ from result set. Cause: java.sql.怎么解决
  5. 数值卡,让数据可视化玩出新花样丨三叠云
  6. Java高并发累加器Striped64
  7. Android黄油刀插件使用记录
  8. 推荐系统架构与机器学习基础理论
  9. 龙泉寺贤超法师:用AI为古籍经书识别、断句、翻译
  10. 284、超详细的光纤熔纤、盘纤教程,值得收藏