`

字符编码浅谈

阅读更多

转自:http://chengxu.org/p/519.html

 

一直就想写一点关于编码的东西,这一点点概念虽然很小,甚者你可以认为这很简单,但实际工作中发现,真正能把几种编码形式,从概念到应用理解清楚的,或者讨论问题中,能把编码这件事解释清楚的,真不多。于是花了周末的一个下午,把这点事儿简单写了写,结合自己工作中的认识,自认为算是说清楚了,贴出来与诸君共勉。
所谓编码,其实就是一种信息的组织传递方式,原始人,没有文字时,跳舞,打手势,严格来讲都是编码,乃至后来的战国时期兴起的烽火,抗战时期的鸡毛信,严格来讲都算一种编码方式,今天重点介绍,日常用的比较多的几个编码概念,ascii,gb2312,gbk,utf8 ,unicode等几种。
先说最简单的,ascii码,如果全世界就英文这一种语言,ascii就可以搞定一切了,简单来总结,ascii码适用所有拉丁文字母,使用7 位二进制数来表示所有的大写和小写字母,数字0 到9、标点符号, 以及在美式英语中使用的特殊控制字符。而最高位为1的另128个字符(80H—FFH)被称为“扩展ASCII”,一般用来存放英文的制表符、部分音标字符等等的一些其它符号。
最高位为1的128个扩展码并不常用,重点介绍一下,最高位为0的128个字符,其中:0~31及127(共33个)是控制字符或通信专用字符(其余为可显示字符),32~126(共95个)是字符(32是空格),其中48~57为0到9十个阿拉伯数字,65~90为26个大写英文字母,97~122号为26个小写英文字母,其余为一些标点符号、运算符号等。

遗憾的是,ascii码只能处理英文了,一遇到我们东方方块字就没辙了,于是,国家某部委,终于干了一件至今我认为比较靠谱,且有技术含量的事儿:制定了gb2312编码规范,全称是中国人民共和国汉字信息交换用码。除了表示了我们常用的简体汉字,还处理了希腊文,日文,及俄文等西方字符。必须承认,这套gb2312标准的实现,比ascii码标准的实现确实要难上几个系数,成千上万的汉字,并不是一个字节,128个符号就能表示的,于是gb2312采用了区位码的概念。何为区位码?可以理解为一块地图,诸侯割据,划分成94个区,然后每个区,又划分成94个位,共划分了94*94个小格子,每个格子表示一个字符,这个字符的编码就是这个格子的区码和位码的组合,这个编码形式就叫区位码。区位码一般用10进制数来表示,如4907就表示区位码中49区第7位,对应的字符是“学”。区位码中01-09区是符号、数字区,16-87区是汉字区,10-15和88-94是未定义的空白区。它将收录的汉字分成两级:第一级是常用汉字计3755个,置于16-55区,按汉语拼音字母/笔形顺序排列;第二级汉字是次常用汉字计3008个,置于56-87区。
但是,这么一来,存在一个问题,区位码编码范围和ascii码存在重叠,重叠的部分,机器无法区分这玩意属于ascii编码,还是属于区位码。于是,为了便于传输和表示,每个字符的区位码,又分别加上了两个数字20H(避免同ascii控制码冲突),和80H(避免同高位为1的扩展ascii冲突),即20H+80H = a0H, 区位码的区号和位号上分别加上A0H就得到了GB2312编码。
所谓gbk呢,也是区位码,只不过,区位图上不再是94*94的划分,又多划分了一些区域,包含了更多的汉字和字符,但编码规范上,完全兼容gb2312,即一个汉字的gb2312编码,和gbk编码完全一样,比gbk更大的汉字编码集是gb18030,同样也是区位码,只不过范围更大一些而已。
终于要说unicode了,天下这么大,如果每种语言,每个字符都用区位码来表示,区位码的范围将会更大,当然这也未尝不可,但问题是,咱们部委的这套编码标准,其他国家的标准委员会未必认同,于是,unincode编码规范,应运而生了。这种编码为每个字符,包括世界上所有语言文字,包括以后可能出现的火星文和不知道啥星文,都分配个一个数字编码,这个编码叫unicode编码,编码范围从0-0x10ffff,最多容纳1114112个字符,按说这就太平了,可是考虑到字的边界问题,必须对这些数字设计一个编码规范,否则一屏幕的数字,你怎么区别,到哪儿算一个完整的字呢?字与字之间如何划分边界呢?于是针对不同的unicode编码规范,出现了utf-8,utf-16,utf-32等编码规则。UTF-8、UTF-16、UTF-32分别以BYTE、WORD、DWORD作为编码单位。“汉字”的UTF-8编码需要6个字节。“汉字”的UTF-16编码需要两个WORD,大小是4个字节。“汉字”的UTF-32编码需要两个DWORD,大小是8个字节。这里重点介绍一下utf-8,这是日常用的最多的。
UTF-8以字节为单位对Unicode进行编码。从Unicode到UTF-8的编码规则如下:
Unicode编码(16进制) UTF-8 字节流(二进制)
000000 – 00007F 0xxxxxxx
000080 – 0007FF 110xxxxx 10xxxxxx
000800 – 00FFFF 1110xxxx 10xxxxxx 10xxxxxx
010000 – 10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0×00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同。UTF-8编码的最大长度是4个字节。从上面的utf8编码规则可以看出,4字节模板有21个x,即可以容纳21位二进制数字。Unicode的最大码位0x10FFFF也只有21位。UTF-8的第一个字节开始的1的个数代表了总的编码字节数,后续字节都是以10开始。
例1:“汉”字的Unicode编码是0x6C49。0x6C49在0×0800-0xFFFF之间,使用3字节模板了:1110xxxx 10xxxxxx 10xxxxxx。将0x6C49写成二进制是:0110 1100 0100 1001, 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。
例2:Unicode编码0x20C30在0×010000-0x10FFFF之间,使用用4字节模板了:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx。将0x20C30写成21位二进制数字(不足21位就在前面补0):0 0010 0000 1100 0011 0000,用这个比特流依次代替模板中的x,得到:11110000 10100000 10110000 10110000,即F0 A0 B0 B0。
utf-16,utf-32不再赘述,与utf-8的编码原理相同,不同的只是编码单位分别是2个字节,和4个字节。
顺便纠正一个日常工作中错误的说法,码农在涉及编码的工作中,常说就是gbk编码到uf8编码的转换,其实这种说法不确切,gbk确实是一种字符集标准,但utf8并不是一种字符集合,严格点说应该是gbk字符集到unicode字符集的转换,转换成的unicode编码,用utf8规则来表示。好像有点绕嘴了,但确实要这么去理解。本人曾遇到过更有甚者,讲gbk也是unicode字符集的一种编码格式,当时无语,你可以有病,但我可没药,这种基本概念要是要搞搞清楚的,工程上的概念,该严谨还是要严谨。
目前主流的编码集,就上述几种,结合自己工作中的认识,简单总结了一下,说到这里顺便提一下,乱码是怎么产生的呢?文件a用utf-8的规则,来存储了一篇文字,电脑的cpu指令却准备用gbk 的区位码规则,来解析这些文字,并显示在屏幕上,于是乱码产生了,所以说,其实本没有乱码,只不过,鸡同鸭讲时,彼此都听不明白而已。

分享到:
评论

相关推荐

    浅谈字符编码.pptx

    本人对字符编码比较感兴趣,整理了一ppt,有需要的拿去。

    浅谈html特殊字符 编码css3 content:"我是特殊符号"

    下面小编就为大家带来一篇浅谈html特殊字符 编码css3 content:"我是特殊符号"。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    浅谈html特殊字符 编码css3 content:”我是特殊符号”

    项目中用到的一些特殊字符和图标 html代码 XML/HTML Code复制内容到剪贴板 <div u00a0class=cross></div>  css代码 CSS Code复制内容到剪贴板 .cross{  width: 20px;  height: 20px;  background-color:...

    浅谈JavaScript中的字符编码转换问题

    主要介绍了浅谈JavaScript中的字符编码转换问题,是JS入门学习中的基础知识,需要的朋友可以参考下

    浅谈python下含中文字符串正则表达式的编码问题

    这是指定一种编码格式,意味着用该编码存储中文字符(也可以是gbk、gb2312等)。 关于测试的几点注意 ——————————————– 注1:代码中有中文,就要在头部指定编码方式,如果用编辑器写代码,还要注意IDE的...

    浅谈java中字节与字符的区别

    主要介绍了浅谈java中字节与字符的区别,字节是java中的基本数据类型,用来申明字节型的变量;字符是语义上的单位,它是有编码的,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,...

    IOI国家集训队论文集1999-2019

    骆 骥 -《由"汽车问题"浅谈深度搜索的一个方面——搜索对象与策略的重要性》 毛子青 -《动态规划算法的优化技巧》 俞 玮 -《基本动态规划问题的扩展》 张一飞 -《求N!的高精度算法》 ## 2002 戴德承 -《退...

    浅谈javascript中字符串String与数组Array

    简单点就是string是字符(串)… 而array是数组…可以放数字啊,字符啊等一系列... //各整数作为unicode编码,并连接成字符串。 var str1 = “liu”.localecompare(“zhan”);//按本系统提供的默认比较规则比较当前字符串

    浅谈编码,解码,乱码的问题

    我们不可避免的会遇到各种各样的编码,解码,或者乱码问题,很多时候,我们可以正常的解决问题,但是说实在的,我们有可能并不清楚问题到底是怎么被解决的,秉承知其然,更要知其所以然的理念,经过一番研究,就有了...

    浅谈python中str字符串和unicode对象字符串的拼接问题

    str字符串 ...unicode是一种编码标准,具体的实现可能是utf-8,utf-16,gbk等等,这就是中文字符串和unicode有密切关系的原因。 python内部使用两个字节存储一个unicode对象(unicode对象并不只能是

    浅谈Java中Unicode的编码和实现

    向大家介绍了Java编程中Unicode编码及实现的相关内容,列举了几个字符不同表达式的比较,以及Unicode平面映射的知识,具有一点点参考价值,需要的朋友可以了解下。

    浅谈在js传递参数中含加号(+)的处理方式

    一般情况下,URL 中的参数应使用 url 编码规则,即把参数字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,空格则编码为加号(+)。 但是对于带有中文的参数来说,这种编码会...

    浅谈C++的几种从键盘输入方式

    每个字节都被解释为字符编码。不管数据类型是什么,输入一开始都是字符数据,然后cin对象负责将数据转换成其他类型 例如 string name; std::cin>>name; std::cout<<name; 当你输入Michael Jackon时,通运行...

    浅谈Python2之汉字编码为unicode的问题(即类似\xc3\xa4)

    Python2中编码相关的问题很是让人蛋疼,特别是中文字符。 比如本文所述的中文网页GBK编码的诡异问题。 现象 例如:盲录職氓聭聵,其实网页里面正常的应该是会员 分析 接着上面的例子,会员这部分乱码通过repr()函数...

    浅谈Mysql如何处理表情,MySql如何存储表情

    场景 最近遇到myql的一个坑,我尝试使用mysql存储相关表情,但接收到的表情都被转化...那么针对历史表的处理,我们经常反馈说变更表结构还是一样,可参考mysql给出的将现有数据库字符编码变更方案即可解决. 作者:Shiner_

    浅谈php中urlencode与rawurlencode的区别

    前段时间说自己遇到了个《URL加号引发错误》的BUG... 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,空格则编码为加号(+)。此编码与 WWW 表单 POST 数据的编码方式是一样的,同时与 applicat

    浅谈PYTHON 关于文件的操作

    以上三个单引号内分别表示:要打开的文件的路径,mode为文件打开方式具体介绍在下文,encoding为文件的字符编码,一般默认为utf-8 2.读写文件: data=f.read() # 读文件 f.write() # 写文件 3.关闭文件: f.close() 4....

    浅谈Unicode与JavaScript的发展史

    Unicode源于一个很简单的想法:将全世界所有的字符包含在一个集合里,计算机只要支持这一个字符集,就能显示所有的字符,再也不会有乱码了。 它从0开始,为每个符号指定一个编号,这叫做”码点”(codepoint)。...

Global site tag (gtag.js) - Google Analytics