ascii、unicode、UTF-8、UTF-16、UCS-2历史及转换

汉字UCS-2编码表.doc 立即下载

文章摘自:https://www.cnblogs.com/tarol/p/7523642.html

最近在看nodejs的源码,看到stream的实现里面满地都是encoding,不由想起以前看过的一篇文章——在前面的随笔里面有提到过——阮一峰老师的《字符编码笔记:ASCII,Unicode和UTF-8》。

  好的文章有一个好处,你每次看都会有新的收获,它就像一款拼图,你每次看都能收获几块碎片,补齐之前的认识;而好文章与拼图不一样的是,好文章是一块无垠的世界,当你不愿局限于当前的眼界的时候,你可以主动走出去,外面要更宽广、更精彩的多。

  闲话说到这,开始聊聊所谓的编码。

  大家都知道,计算机只认识0和1,不认识什么abc。如果想让计算机显示abc,那么就要有一张1对1的表,用这张表告诉计算机,什么样的二进制串——比如(010101011100)——代表的是a,什么样的串代表的是b,这个表描述二进制串到符号的对应关系。ASCII就是这么一张最早也是最简单的表,这张表简单到包含128个符号,比如10个数字、26个小写字母、26个大写字母,和一堆标点符号(如英文句号、逗号等)还有控制字符(如回车、tab等)。那为什么是128,不是100或182?因为128正好用7个bit(一个0或者1为一个bit)表示。那么为什么不是256对或者更多?因为对于英语地区128个符号够用了,而在ASCII推出的那个年代(1967),大家还没开始着眼全球——这点从名字就可以看出来,ASCII = American Standard Code for Information Interchange(美国信息交换标准码),根本就没打算让别人上车。

  然后其他语言地区很快入场了,而且随着八位机的普及,1字节=8bit成为了共识,大家都盯上了多出来的128个位置。这个时代群魔乱舞,基本是个公司就想染指这块标准,乱象直到1985年才通过ISO/IEC 8859把EASCII确定下来。

  而在这个过程中,有一个地区的人根本就不跟你玩,就是意表文字地区,明白的说,主要是中日韩。开玩笑,256个位置,你全让出来都不够我做两句诗。老司机不带怎么办,只能自己开车了,首先是日本站出来,于1978年出台了最早的汉字编码,然后中国大陆、中国台湾、韩国都在80年代出台了自己的汉字编码。这个时候,大家各自玩各自的没什么问题,聚在一起,问题就来了。比如一篇文章中包含中日韩三种文字,一串01的组合在中国的编码对应的是某个字,在日本的编码对应的却是另一个字,那计算机最后到底显示哪个字,计算机也很为难。有冲突怎么办,开个会通通气吧,于是大家坐在一起成立了个组织,叫CJK-JRG(China, Japan, Korea Joint Research Group)。虽然这个组织折腾了很多年,而且最终提案也被否决了,但是为另一个方案提供了足够的信息,就是Unicode。

  Unicode项目于1987年启动,在吸收了CJK-JRG的方案后于1992年6月份发布1.0.1版(之前的1.0.0没有包含汉字),迄今为止还在增修,最新的版本是2017.6.20公布的10.0.0。最早的Unicode被设计为16bit,即每个符号占2byte,最多表示65536个符号。而后随着内容的增加,又基于原有设计不变的原则,将最早的65536个字符集合称为基本多文种平面(Basic Multilingual Plane, BMP),并添加16个辅助平面(总共支持65536 * 17 = 1114112个符号)。这样一来,原来的16bit就不够用了,需要21bit才能准确描述一个符号,相当于3byte不到,但是为了以后扩展方便及统一,辅助平面的符号要求使用4byte描述。

  Unicode解决了全世界人民用一套符号编码的问题,但却没有解决另一个问题,就是怎么存储的问题。按照一般的想法,所有的符号都必须以最长的Unicode符号的标准来存储,也就是4byte,这样才不会有信息丢失。但是这样的话,对于全部是英文的文档,要浪费掉3/4的区域,对于大多数汉字,即BMP中的汉字,也要浪费掉1/2的区域。所以野蛮的使用4byte进行存储是不可取的,那么就要设计一套变长的规则来处理不同类型的符号,这时候UTF8、UTF16等就应运而生了,也就是说UTF8、UTF16是Unicode的一种实现方案(标准的说法,是Unicode字符编码五层模型的第三层,如果你对五层模型感兴趣,跳转《刨根究底字符编码》)。

  先说UTF8,UTF8是完全变长的,占用1-6byte,乍一看,怎么比直接用4byte存储还多出一半呢?其实占用4byte的情况是很少的,少到在几乎可以忽略不计,而5、6byte基于当前16个辅助平面的情况下还用不上。一般来说,英文占用1byte,中文占用3byte(CJK-JRG最早提供给Unicode的20000多个符号位于位于U+4E00–U+9FFF,这块区域的符号统一都占3byte),所以一般来说使用UTF8可以节省1/4到3/4的存储区域。这样似乎解决了存储的问题,但却带来了另一个问题,即识别的问题。比如我给你3byte的二进制信息,告诉你这代表了一个字,那你肯定很快能知道是什么字,但我如果不告诉你字数呢,是一个字,两个字,还是三个字?你根本识别不出来这一串二进制是什么。这就是变长的方案需要解决的第二个问题,告诉读取方哪几个byte是一组的,UTF8的规则很简单,我直接从阮老师的博客里搬运过来。

1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

 

Unicode符号范围UTF-8编码方式
(十六进制)(二进制)
0000 0000-0000 007F0xxxxxxx
0000 0080-0000 07FF110xxxxx 10xxxxxx
0000 0800-0000 FFFF1110xxxx 10xxxxxx 10xxxxxx
0001 0000-001F FFFF11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0020 0000-03FF FFFF111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0400 0000-7FFF FFFF1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

  简单的说,你收到很多个byte的二进制,从第一个byte开始读,数第一个0出现之前的1,有几个1就代表前面几个byte是一组的,0个1就代表当前的这个byte孤家寡人一个。然后跳过这个组的所有byte,继续之前数1的环节。分好组后,按组找到上表右边的规则,把规则内x的位置保留下来,01的位置全部扔掉(01代表的位置是UTF8的元数据,x代表的位置才是Unicode的数据),拼成新的二进制串,这个串就是Unicode了。举个栗子:

11100110 10001000 10010001 11100110 10011000 10101111 01110100 01100001 01110010 01101111 01101100

  以上有11个byte,我们从第一个byte11100110开始,数第一个0前面的1的数量,有3个1,代表3个byte是一组的。然后我们跳过这3个,第四个byte是11100110,继续数1得出有3个1,然后又给这3个byte分组。跳过这三个,到了第7个byte,这往后的5个byte都是以0开头,说明每个byte为1组。现在我们分好组了,有7个组,分别是

[11100110, 10001000, 10010001], [11100110, 10011000, 10101111], [01110100], [01100001], [01110010], [01101111], [01101100]

  现在我们按组找到表右对应的行,第一组、第二组对应第五行,其他组对应第三行,我们把行内x对应的位置保留,10的位置删除,得到新的数组

[0110, 001000, 010001], [0110, 011000, 101111], [1110100], [1100001], [1110010], [1101111], [1101100]

  然后把组内的二进制串起来得到Unicode

[0110001000010001], [0110011000101111], [1110100], [1110100], [1100001], [1110010], [1101111], [1101100]

  这时候我们再按byte进行拆分以便阅读,并且在高位补0

[01100010 00010001], [01100110 00101111], [01110100], [01110100], [01100001], [01110010], [01101111], [01101100]

  再转换成16进制

[62 11], [66 2F], [74], [61], [72], [6F], [6C]

  这时候我们打开F12,在控制台输入对应的Unicode(语法要求必须使用4位16进制数字)

'\u6211\u662f\u0074\u0061\u0072\u006f\u006c'

  得到了对应的字符串“我是tarol”。

  好了,以上是UTF8的内容,之所以叫UTF8是因为这个规则下的符号,最少占8bit。那么UTF16就好理解了,在这个规则下,每个符号最少占16bit。UTF16的规则说起来更简单,当符号位于BMP中时,占用2byte,在符号位于辅助平面时,占用4byte。那既然是变长的,又碰到了上面的问题,怎么识别这一块是4byte为一组还是2byte为一组?

  这里就要提到Unicode的保留区块了,Unicode规定从U+D800到U+DFFF之间是永久保留不赋予任何符号的。也就是正常情况下,2byte如果落在这个范围内,那么就是Unicode的非法字节。而UTF16的做法就是把辅助平面的Unicode码进行处理,变成4个字节,并且两两落在非法区域内,读取方读到了非法字节,就可以界定这里是4byte为一组,不然就是2byte为一组。那么UTF16这个转换的算法又是怎样的呢?

  1. 首先按现在17个平面的限制,辅助平面的码位是U+10000到U+10FFFF,我们得到了一个辅助平面的Unicode码时,先减去BMP的码数0x10000,得到的数介于0到0xFFFFF之间,最多用20bit表示
  2. 然后我们把20bit从中间隔开,分为高位的10bit和低位的10bit
  3. 我们知道10bit的取值范围是0到0x3FF,高位的10bit加上固定值0xD800,得到的值叫做前导代理(lead surrogate),范围是0xD800到0xDBFF
  4. 低位的10bit加上固定值0xDC00,得到的值叫做后尾代理(tail surrogate),范围是0xDC00到0xDFFF。这样一来,不仅高位和低位都落在了保留区块内,而且彼此还做了区分。

  还是举个例子。

  

英飞凌TC3xx的GTM模块到底有多强?从PWM生成到电机驱动,一篇讲透车载定时器核心 本文深入解析英飞凌TC3xx系列中的GTM模块在汽车电子领域的强大功能,从PWM生成到电机驱动的全链路设计。通过模块化架构和硬件级解决方案,GTM显著提升系统精度和响应速度,适用于电机控制、电源管理等复杂场景。文章结合实战经验,详细拆解GTM的技术实现和性能优势。 阅读详情

相关推荐

OpenCV卡尺工具实战:5步搞定工业级圆与直线拟合(附完整C++源码)

本文详细介绍了使用OpenCV卡尺测量工具实现工业级圆与直线拟合的5个关键步骤,包括核心原理、环境配置、边缘点提取优化、鲁棒性几何拟合实现及QT集成技巧。通过模块化C++源码和实战案例,帮助开发者快速掌握高精度尺寸测量技术,适用于机械零件、PCB板等工业检测场景。

uran的专栏 843

所谓编码--泛谈ASCII、Unicode、UTF8、UTF16、UCS-2等编码格式

  最近在看nodejs的源码,看到stream的实现里面满地都是encoding,不由想起以前看过的一篇文章——在前面的随笔里面有提到过——阮一峰老师的《字符编码笔记:ASCII,Unicode和UTF-8》。   好的文章有一个好处,你每次看都会有新的收获,它就像一款拼图,你每次看都能收获几块碎片,补齐之前的认识;而好文章与拼图不一样的是,好文章是一块无垠的世界,当你不愿局限于当前的眼界的时...

weixin_30745641的博客 874

Simulink实战:火电机组一次调频与AGC协同控制建模与仿真解析

本文详细解析了如何使用Simulink进行火电机组一次调频与AGC协调控制的建模与仿真。通过系统架构设计、参数设置和模块实现,阐述了如何实现两者的协同控制,确保电网频率稳定。文章提供了实用的建模技巧、参数整定经验和性能评估方法,为电力系统仿真工程师提供了有价值的实践指导。

c7d8e9的博客 308

ASCII控制字符在vi和notepadd++中的表示法

背景信息:ASCII控制字符:十进制为0~31,127在从Hive导出记录时,可以通过ASCII码来指定分隔符,但不是很清楚是否所有的控制字符都可以用于作为分隔符,以及有什么区别,因此通过实际导出过程进行了测试与验证。结论:十进制 在Vi(CentOS)中的表示法 0 ^@ 1 ^A 2 ^B 3 ^C ... 24 ^X 25 ^Y 26 ^Z 27 ...

日进一步 3787

金蝶云ERP远程办公指南:零公网IP实现安全内网穿透访问

本文详细介绍了如何利用内网穿透技术,在无需公网IP和复杂路由器设置的情况下,安全远程访问内网部署的金蝶云ERP系统。通过使用cpolar工具,逐步指导用户创建加密隧道、配置固定域名,并实现管理中心与数据中心的远程登录,有效解决了企业员工在外出或居家办公时的核心业务系统访问难题。

weixin_29229261的博客 269

【数据攻略】字节面试真题(含答案)+100道面试题库

数据攻略

qq_40002713的博客 4102

Notepad++支持插入特殊字符

(Notepad++支持插入特殊字符) 导入大数据提供的unl数据文件时,文件的分隔符为ACSII的0位,在sql脚本中无法打出该特殊字符(分隔符) 然后才发现,原来Notepad++中,也是可以输入控制字符的: 编辑(E) ⇒ Character Panel 然后就调出了ASCII Insertion Panel,显示了ASCII字符表,包括了控制字符: 双击ASCII Insertion Panel中任一(普通或控制)字符,比如DLE,DC1这两个控制字符,就可以插入对应的控制字符了。 ...

weixin_45604616的博客 4247

揭秘大厂智能生产调度AI系统架构:架构师拆解中台化设计3大优势

智能生产调度AI系统是基于AI算法(如遗传算法、强化学习、深度学习),结合生产数据(如订单、设备、库存、人员),自动生成最优生产计划与调度方案的系统。最大化设备利用率(减少停机时间);最小化生产周期(快速交付订单);优化库存水平(降低积压与短缺);提升准时交货率(满足客户需求)。维度传统调度系统智能调度AI系统决策逻辑规则引擎+人工经验AI算法(预测+优化)数据处理手工汇总+静态数据实时数据整合+动态更新适应能力固定场景(如单一产品、单一工厂)

AI Python 编程之道的博客 759

UCS2-little endian转码(utf16)

ucs2文件乱码问题

weixin_43972720的博客 701

ThingsBoard集群部署之k8s

今天终于有时间去搞这个啦,拖了很久了,一直没时间,因为我本地没有那么多机器资源,开虚拟机不够,如果租用阿里云服务器,需要有充值的时间,因为这个费用是按小时付费,需要有连贯的时间来搞才行,今天恰好有时间,就开始搞了,弄成功搞出来了,特地写博客记录下来。

AldrichEugene 1174

机器人中的数值优化(十四)——罚函数法(Penalty Method)、障碍函数法(Barrier Method)、拉格朗日松弛法(Lagrangian Relaxation)

本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考,主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等,本系列文章篇数较多,不定期更新,上半部分介绍无约束优化,下半部分介绍带约束的优化,中间会穿插一些路径规划方面的应用实例

慕羽★的博客 5217

计算机编码总结(上)

Nodepad++相信大家都有用过,编码那一栏有ANSI格式编码,UTF-8格式编码,UTF-8-BOM格式编码,UCS-2 Big Endian以及UCS-2 Little Endian等等,这些其实就是我们常说的编码方式。你可能会想问为什么没有ASCII,Unicode,UTF-16呢,因为你肯定在写程序的时候用过,后面我们会说到这种可以说是广为流传的误区吧。 以上提到的Notepad++中...

Huadong_eddy的博客 663

华为HCIE之TS部分整理

TroubleShooting 整体拓扑 1. MSTP 题目需求:site1 中,CLIENT1 属于 VLAN12,CLIENT3 属于 VLAN34;MSTP 中的 VLAN12 属于 instance1,vlan34 属于 instance2;两个 instance 的主备根桥分别在 SW1 和 SW2 上,并且要求 CLIENT1访问 R1 时经过的路径是 SW3-SW1-R1;同时要求 CLIENT3 访问 R1 时经过的路径是SW3-SW2-R1; 排错思路: ①查看SW3 SW1 SW

ledrsnet的博客 5756

谈谈Unicode编码,简要解释UCS、UTF、BMP、BOM等名词

本文转自:http://www.52rd.com/Blog/Detail_RD.Blog_thieven_4865.html 这是一篇程序员写给程序员的趣味读物。所谓趣味是指可以比较轻松地了解一些原来不清楚的概念,增进知识,类似于打RPG游戏的升级。整理这篇文章的动机是两个问题:   问题一: 使用Windows记事本的“另存为”,可以在GBK、Unicode、Unicode big ...

junmail的专栏 122

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

中文编码规则一网打尽

Unicode字符编码规范 Unicode是一种字符编码规范 。 先从ASCII说起。ASCII是用来表示英文字符的一种编码规范,每个ASCII字符占用1个字节(8bits)因此,ASCII编码可以表示的最大字符数是256,其实英文字符并没有那么多,一般只用前128个(最高位为0),其中包括了控制字符、数字、大小写字母和其他一些符号。 而最高位为1的另128个字符被成为“扩展ASCII”,一

醉江楼的专栏 1492

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

关于字符、字符集、编码和Unicode

UTF-8是Unicode的一种实现方式。而Unicode是一种字符集。本文介绍了Unicode和Unicode的集中存储方法,同时介绍了Unicode与UTF-8编码的转换方法。

猫步旅人- 程序员的旅途 1142

谈谈Unicode编码,简要解释UCS、UTF、BMP、BOM等名词 (ZT)--转贴

转贴至:http://www.guidemarvin.com/mypool/index.php/develop/the-chaos-of-character-coding/这是一篇程序员写给程序员的趣味读物。所谓趣味是指可以比较轻松地了解一些原来不清楚的概念,增进知识,类似于打RPG游戏的升级。整理这篇文章的动机是两个问题: ...

zjumty 202

字符集编码Unicode ,gb2312 cp936

这是一篇程序员写给程序员的趣味读物。所谓趣味是指可以比较轻松地了解一些原来不清楚的概念,增进知识,类似于打RPG游戏的升级。整理这篇文章的动机是两个问题:问题一:使用Windows记事本的“另存为”,可以在GBK、Unicode、Unicodebigendian和UTF-8这几种编码方式间相互转换。同样是txt文件,Windows是怎样识别编码方式的呢?我很早前就发现Unicode、Unico...

weixin_30437337的博客 133

字符编码介绍

1.ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串。每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出 256种状态,这被称为一个字节(byte)。也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从 0000000到11111111。 上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制

Edward_qing_Lee的专栏 1292

java:ASCII、ANCI、非ASCII、Unicode、UTF-8等编码形式总结

ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串。每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,...

1584

关于字符编码,你所需要知道的-(转载)

关于字符编码,你所需要知道的   字符编码的问题看似很小,经常被技术人员忽视,但是很容易导致一些莫名其妙的问题。这里总结了一下字符编码的一些普及性的知识,希望对大家有所帮助。 还是得从ASCII码说起   说到字符编码,不得不说ASCII码的简史。计算机一开始发明的

oneingdust的专栏 446

字符集——从ASCII到Unicode

最近被文件读写的乱码搞郁闷了,现在来研究一下。 首先了解一下字符编码的历史。 ASCII,这无需多说(American Standard Code for Information Interchange)美国信息交换标准代码,是一套基于拉丁字母的电脑编码系统,至今为止共定义了128个字符,可以显示现代英语。但是随着万维网的发展,多语言的处理使得该标准不再适用,逐渐被之后的Uni...

Chris0308的博客 216

编码 区别 由来

10进制,2进制,8进制,16进制 基础 2进制就是每一位用0,1表示; 8进制就是每一位用0,1,2,3,4,5,6,7表示; 16进制就是每一位用0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F表示字符和字节的区别 1个字节等于8个bit位,每个bit位又0/1两种状态也就是说一个字节可以表示256个状态,计算机里用字节来作为最基本的存储单位。一般来说,英文状态下一个字母或数字

千越的烂笔头 517

Ansi、Unicode、UTF8字符串之间的转换和写入文本文件

转载请注明出处http://www.cppblog.com/greatws/archive/2008/08/31/60546.html 最近有人问我关于这个的问题,就此写一篇blog Ansi字符串我们最熟悉,英文占一个字节,汉字2个字节,以一个\0结尾,常用于txt文本文件 Unicode字符串,每个字符(汉字、英文字母)都占2个字节,以2个连续的\0结尾,NT操作系统内核用的是这

机器视觉之家 1万+

一个C++builder工程移值到RAD STUDIO的视频

这个视频的主要内容是讲解了各种字符特别是UNICODE等的相关知识等一些方面相信你可以从中学到一些知识点!http://v.youku.com/v_show/id_XMTQxNTkzOTQ4OA==.html 转载于:https://blog.51cto.com/gunxsword/1858216...

weixin_33909059的博客 204

Java中Unicode与utf-8、utf-16的关系

转载于:https://www.cnblogs.com/fnlingnzb-learner/p/6163205.html 基础知识: 字符集合(ASCII、Unicode):由一套用于特定用途的字符组成,例如支持西欧语言的字符集合,支持中文的字符集合。字符集合只定义了符号和他们的语意,其实跟计算机没有直接关系。现实生活中,不同的语系有自己的字符集合,例如藏文有自己的字符集合,汉文有自己的字符集...

weixin_30241919的博客 2913
上一篇: S3C2440 DMA工作原理
下一篇: vmware网络设置
迟到的火车
博客等级 码龄16年 13粉丝 12原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值