编码简介

编码简介

 

最近被字符集搞得头大,基于为自己扫盲的目的,索性收集资料研究一下,现将各方资料归纳成本文。这里并不想把复杂的规则说明一大通。如有需要,请参照其他资料或本文给出的参考资料。 
        如有错误,欢迎指正。 
        [顺便发下牢骚,je的编辑器真TMD难用,排版排得我半死] 

基础知识 

字节和字符 
        字节(octet):顾其英文名而思义,就是一个八位的存储单元,取值范围一定是0~255; 
        字符(character):就是一个语言上的符号,"中"字就是一个字符。字符所占的大小由其编码方式解决,比如"中"在UTF-8中占3个字节(0xE4A8AD),而在GBK中,则占两个字节(0xD6D0)。 

字符集和编码 
        字符集:字符的集合,像Unicode字符集,目标就是收纳了这个世界上所有语言的文字、符号等; 
        字符编码:注意,字符集只是规定了有哪些字符,而最终决定采用哪些字符,每一个字符用多个字节表示等问题,则是由编码来决定的。像Unicode字符集的编码方式有很多,诸如UTF-8、UFT-16、UTF-32等。 
        字符集和字符编码是分开的概念,但有时候称呼上会有些模糊,我们经常笼统地称这些Unicode字符集的编码为Unicode编码。 

内码 
        内码:操作系统内部的字符编码。像早期的DOS采用的是ASCII,而现在的操作系统大把采用Unicode编码。 

编码简史 

        在讲各种编码之前,有必要先讲一个编码这个令人头疼的家伙的历史,这样有助于大家理解今天的编码世界为什么会是这样一个局面。 
        计算机对多语言的支持,大致为分以下三个阶段。 
        阶段一:ASCII时代。计算机是DOS时代的计算内码是ASCII码,ASCII的表示范围就是0到127那几个符号,这意味着,DOS时代的计算机只能显示英文,而无法支持其他语言。没办法,由于英文系国家开创了并继续主导了计算机的世界,他们自然而然地认为全世界的文字用8个字节表示足矣。
        阶段二:ANSI时代。由于上述原因,像我们这些非英文系的国家的为了显示自家的文字,不得不一开始就得面对字符编码的问题,不同国家不同地区都创建了自己的编码标准。像是中国大陆是GB2312及后来的GBK,台湾是BIG5,日本是JIS。ASCII字符集,以及这些由此派生并兼容的字符集称为ANSI字符集。 
        阶段三:Unicode时代。为了和谐而出现,相较于以上两个阶段,这个时代称为国际化时代,适应了跨平台,跨语言之间交换信息的需求。 

Unicode和UTF系列 

Unicode 
        Unicode 字符集收录了这世界上所有的文字符号和特殊符号。对于每一个符号都定义了一个值,称为代码点(code point)。代码点可以用2个字节表示(UCS-2),也可以用4个字节(UCS-4编码)。 

UTF系列 
为什么出现UTF编码? 
        UCS编码虽然定义了每个代码点的编码方式,但是没规定如何传输和存储。比如,在UCS-2码中,英文符号是在ACSII码的前面加上一个0 byte,像"A"的ASCII码 0x41,在UCS码中就是0x0041,这样,对于英文系统来讲会出现大量的0 byte,造成不必要的浪费。而且容易存在对现在ASCII码不兼容的问题。所以这个重担就落在了UTF编码身上,全称是Unicode Transformation Format。 
什么是Endian? 
        我们知道"中"字的UFT-16编码是0x4E,0x2D,但是传输存储的过程中,字节的顺序有可能是(0x4E,0x2D),也可能是(0x2D,0x4E),这就是涉及一个字节序的问题。对于前一种,我们称为Big Endian(大尾,也就是高位在前),而后一总称为Little Endian(小尾,低位在前)。 
        那我们如何知道在不清楚哪一"尾"的情况下进行解析? 
先人已有解决的办法,就是在最前面加多2个字节,OxFEFF表示BE,而0xFFFE表示LE。(注:OxFEFF是实际上不存在的字符,所以正常情况下是不会使用到的,所以,不用担心出现与正常的字符数据冲突的问题),这就是所谓的BOM(Bill Of Material)。 
        UTF系列都存在LE,BE,BOM,无BOM几种版本。 
        比如"中国"的各个版本UTF-16字符编码如下: 
编码字节序列
UTF-16BE4E,2D,56,FD
UTF-16LE2D,4E,fD,56
UTF-16(BOM,BE)FE,FF,4E,2D,56,FD
UTF-16(BOM,LE)FF,FE,2D,4E,fD,56


UFT-8 
        UTF-8采用的是变长码的方式,其编码规则如下: 
代码点值的范围(16进制)第1字节第2字节第3字节
0000 0000-0000 007F0xxxxxxx0-127)
0000 0080-0000 07FF110xxxxx (192-223)10xxxxxx (128-191)
0000 0800-0000 FFFF1110xxxx (224-239)10xxxxxx (128-191)10xxxxxx (128-191)


        注:x的内容是将左边代码点的二进制值依次注入。 
        理论上UTF-8可以达到6个字节编码(上表省略后3位字节以上的编码方式),但实际上,我们一般只采用0x0000 0000 到0x0000 0000FFFF的范围内的字符,也就说UTF-8实际上只采用了3个字节编码。 
        UTF-8除了省空间和兼容ASCII的优点后,其编码方式(类似于哈夫曼编码,很容易判断出1个字节及其后面的字节数)决定了它以下两个优点: 
        1、与字节顺序无关, 可以在不同平台之间交流。 
        2、容错能力高, 任何一个字节损坏后, 最多只会导致一个编码码位损失, 不会链锁错误(如GB码错一个字节就会整行乱码) 

UTF-16和UTF-32 
        UTF-16是变长码,大致上相当于UCS-2码的直接实现,但是也有一部分UCS-4的字符。所以可以猜到,它大部分是采用2个字节编码,而有部分特殊符号采用3字节编码,所以大致相当于20位编码, 值在0到0x10FFFF之间。 
        UTF-32用四个字节表示代码点,这样就可以完全表示UCS-4的所有代码点。 

GB2312、GBK和 GB18030 
        简单来讲,这三者是这样一个关系:GB2312扩展便成了GBK,GBK扩展便成了GB18030。后者都对前者兼容。 
        GB2312:采用2个字节。简体字的编码规范,也包括其他的符号、字母、日文假名等,共7445个图形字符,其中汉字占6763个 
        GBK:采用了2个字节。GB2312明显收录的汉字不够,于是增加了大量不常用汉字,还加入了几乎所有的Big5中的繁体汉字之后便成了GBK。 
        GB18030:与前两者不同,采用了变长的编码方式,有1、2、4个字节的编码长度。1个字节编码与ASCII兼容,2个字节编码与GBK兼容,4个字节主要是收录了少数民族的文字等。GB18030诞生的原因类似于GBK,就是增加了大量的汉字,多收录了藏文、蒙文、维吾尔文等主要的少数民族文字。GB18030现在是国家非手持/非嵌入式设备的强制性标准。 
但是GB18030与前者不同的是,所有的Unicode编码都可以转换为GB18030,而且GB18030除了兼容GBK以及Unicode的BMP部分外,其余的Unicode扩展平面和它的4字节扩展平面都是简单直接的映射 
        其具体映射关系的计算参见《GB18030编码研究以及GBK、GB18030与Unicode的映射》:[http://blog.csdn.net/fmddlmyy/archive/2008/04/13/2288312.aspx]  
        如果说GB2312、GBK是ANSI时代的产物,为什么如今还需要制定GB18030呢?以下引用官方的话:"世界许多国家和地区从方便本国和民族应用的角度出发,制定了相应的编码标准和内码体系,如日本的JIS X 0208和JIS X 0212,韩国的KS C 5601和KS C 5657等,这是国际上采用的通行惯例。制定GB 18030同样符合国际惯例,它全面兼容GB 2312,在字汇上兼容GB 13000.1,可以充分利用已有资源,保证不同系统间的兼容性,最大限度地共享资源,为我国软件产业留有巨大的发展空间。可以相信,GB 18030的实施将有利于国产软件的发展并形成规模,使我国的中文信息技术再上一个台阶。" 

        GB2312、GBK的编码范围如下: 
名称第一字节第二字节
GB23120xA1-0xF7(161-247)0xA1-0xFE(161-254)
GBK0x81-0xFE(129-254)0x40-0xFE(64-254)


        GB18030编码范围如下: 
字节数码位空间
单字节0x00~0x7F (0-127)
双字节第一字节在0x81~0xFE (129-254)第二字节在0x40~0x7E,0×80至0×FE(64-126),(128-254)
四字节第一字节在0x81~0xFE之间 (129-254) 第二字节在0x30~0x39之间 (48-57) 第三字节在0x81~0xFE之间 (129-254) 第四字节在0x30~0x39之间 (48-57)


ASCII和ISO 8859-1 
        ISO 8859-1就比较简单了,我们知道ASCII码是从0x00到0x7F,也就是还有1位没有用到,ISO 8859-1就是在空置的0xA0-0xFF的范围内,加入192个字母及符号,藉以供使用变音符号的拉丁字母语言使用。所以ISO 8859-1又称Latin-1。 

其他编码 
        这里"编码"的含义与以上不同,并不是指字符集的编码,而是一种对文本加工处理的编制方式。因为在开发过程中,也会经常遇到,所以一并介绍。 

application/x-www-form-urlencoded 

        我们在提交表单的时候,常常会看到形如http://localhost:6888/aomstudy/Servlet1?name=%D6%D0%B9%FA 
这样的地址,这些就是application/x-www-form-urlencoded格式编码后的字符串。包括用POST提交表单内容默认是使用这种编码方式。另一种是multipart/form-data,用于有大量非ASCII码文本或二进制数据时,因为这时使用application/x-www-form-urlencoded需要大量的转换,需要耗费太多时间。 
        为什么需要这个application/x-www-form-urlencoded编码?我还不是很明白。个人猜测是:以下规则提到的安全字符都是7位的ASCII字符,虽然HTTP协议支持任意字符,但由于历史原因,在HTTP传输过程,只能保证这7位是安全的,也就是说不被当作其他用途,比如用作控制符等。 
        application/x-www-form-urlencoded的编码规则如下: 
        1.字母数字字符 "a" 到"z"、"A"到 "Z" 和 "0" 到"9" 保持不变。 
        2.特殊字符 "."、"-"、"*" 和"_" 保持不变。 
        3.空格字符 " " 转换为一个加号"+"。 
        4.所有其他字符都是不安全的,因此首先使用一些编码机制将它们转换为一个或多个字节。然后每个字节用一个包含3个字符的字符串"%xy" 表示,其中 xy 为该字节的两位十六进制表示形式。 
        注:以上URL中使用的是GBK编码,原文是http://localhost:6888/aomstudy/Servlet1?name=中国 

Base64 
        介绍之前,先给一段"乱码",让我们有一个感观的认识。 
u7bTrcC0tb1BcHVzaWO1xMrAvec= 
是不是很眼熟?是的,在电子邮件中我们经常见到。Base64可以用来将binary的字节序列数据编码成ASCII字符序列构成的文本。主要应用在电子邮件技术、LDIF档案等。 
        Base64怎么编码?简单来讲,Base64不管你使用的是什么编码,UTF-8也好,ASCII也好,它的眼里只有二进制序列,比如说"中国"GBK编码的二进制序列是[11010110],[11010000],[10111001],[11111010]。那么接下Base64 会做以下几件事: 
        一、Base64按照每3个字节一组(共3*8=24位),依次编入4个字节里。 
只使用低位6个位(共4*6=24位),每个字节前两位置0。值的范围在0到63。 
如果不是3的倍数怎么办?就先全部补[01000000](为什么不是0?因为0是有意义的),比如上面最后一个字节[11111010]变成:[00111110],[00100000],[01000000],[01000000],解码时,由于只考虑低6位,而这个值用了第7位,所以不会影响到正常字符的解码。 
        最终转换后成了这样[00110101],[00101101],[00000010],[00111001],[00111110],[00100000],[01000000],[01000000]         
        二、根据编码的值转换成对应的ASCII字符。对应规则如下: 
ASCII字符ASCII字符ASCII字符ASCII字符
0A17R34i51z
1B18S35j520
2C19T36k531
3D20U37l542
4E21V38m553
5F22W39n564
6G23X40o575
7H24Y41p586
8I25Z42q597
9J26a43r608
10K27b44s619
11L28c45t62+
12M29d46u63/
13N30e47v64(pad)=
14O31f48w
15P32g49x
16Q33h50y


         [00110101],[00101101],[00000010],[00111001],[00111110],[00100000],[01000000],[01000000]的十进制值分别经[53],[45],[2],[57],[62],[32],[64],[64],找到相应的ASCII值,最终,我们得到编码后的字符串为1tC5+g== 
         注:以上"乱码"原文为"欢迎来到Apusic的世界"。 



参考资料 
         1.《Unicode详解》:http://tech.idv2.com/2008/02/21/unicode-intro/ 
         2.《Unicode、UCS和UTF编码简介》:http://hi.baidu.com/%D0%DB%CF%D8/blog/item/f3e0d7f221c09c12b17ec512.html 
         3.《GB18030编码研究以及GBK、GB18030与Unicode的映射》:http://blog.csdn.net/fmddlmyy/archive/2008/04/13/2288312.aspx 
         4.《汉字编码问题》:http://www.css8.cn/css8_document/gb2312.htm 
         5.《Java:Unicode简介》:http://tech.it168.com/oldarticle/2006-11-09/200611092313338.shtml 
         6.《字符,字节和编码》:http://www.regexlab.com/zh/encoding.htm 
         7.《ISO 8859-1》:http://baike.baidu.com/view/758577.htm 

         8.《Base64》:http://zh.wikipedia.org/wiki/Base64 

转载于:https://www.cnblogs.com/DrWang/archive/2011/05/11/2042826.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/378434.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2013年5月7日---JS中的正则

/*(1)RegExp对象的test方法------------------C#中的isMatchvar num1d23; //一个字符串var regnew RegExp(^\\d$); //准备正则alert(reg.test(num)); //开始匹配并弹出--false*//*(2)ReExp对象的test方法var num123;var regnew RegExp(/^\d$/);ale…

八、关于防水透湿整理

1,防水透湿整理加工技术的类型? 收集资料阶段 按照加工方式分类 防水透湿织物按照加工方式可分为高密织物、涂层织物和层压织物。不同加工方式所对应的织物各有特色。高密织物产生于 20 世纪 80 年代,它的密度可达到普通织物的 20 倍。在晴朗天气时,纱线孔隙大约为 10 μm…

linux qt 音频文件怎么打开,Qt:获取Linux中可用音频设备的列表

我想要获取我的Linux系统上可用的所有音频设备的列表。然后我会将这个列表显示在一个组合框中,用户将从中选择用于录制/播放的设备。根据用户的选择,我将构建QAudioInput和QAudioOutput进行录制/播放。Qt:获取Linux中可用音频设备的列表根据Q…

c# uri.host_C#| Uri.GetLeftPart()方法与示例

c# uri.hostUri.GetLeftPart()方法 (Uri.GetLeftPart() Method) Uri.GetLeftPart() method is an instance method that is used to get a specified part from the given URI based on passed UriPartial enum. Uri.GetLeftPart()方法是一个实例方法,用于基于传递的…

求质数算法的N种境界 (N 10) zz

★引子 前天,俺在《俺的招聘经验[4]:通过笔试答题能看出啥?》一文,以"求质数"作为例子,介绍了一些考察应聘者的经验。由于本文没有政治敏感内容,顺便就转贴到俺在CSDN的镜像博客。   昨天&…

【智能车Code review】——小S与中S道路判断

博主联系方式: QQ:1540984562 QQ交流群:892023501 群里会有往届的smarters和电赛选手,群里也会不时分享一些有用的资料,有问题可以在群里多问问。 系列文章 【智能车Code review】—曲率计算、最小二乘法拟合 【智能车Code review】——坡道图像与控制处理 【智能车Code re…

Python匿名函数---排序

一、列表的排序 nums [1,2,3,5,4,7,87,4,9,56,44,7,5] nums.sort()#默认从小到大排序 nums#结果为:[1, 2, 3, 4, 4, 5, 5, 7, 7, 9, 44, 56, 87]nums [1,2,3,5,4,7,87,4,9,56,44,7,5] nums.sort(reverseTrue)#从大到小排序 nums#结果为:[87, 56, 44, …

linux 内核编译需要多大空间,编译2.6.28内核出错。。。。空间不足。而/tmp/还有好几G...

编译2.6.28内核出错。。。。空间不足。而/tmp/还有好几G发布时间:2009-01-02 16:56:47来源:红联作者:weixq316今天闲来无事,就去下载了最新的内核--2.6.28来编译安装。。。:0)1放在/usr/src/2.6.28/中编译。。。。。我的/usr还有1G多的空间。…

如何用vi 复制第5行到第10行并粘贴到第12行之后

方法一: 光标放到第五行,输入:y6y光标放到第12行,输入:p方法二:命令行模式下输入:5,10 co 12方法三:延伸一下, 有时候不想费劲看多少行或复制大量行时,可以使用标签来替代光标移到起…

go zap去除程序名称_适用于Zip,Zap和Zoom游戏的Python程序

go zap去除程序名称Write a python program that displays a message as follows for a given number: 编写一个python程序,显示给定数字的消息如下: If it is a multiple of three, display "Zip". 如果是三的倍数,则显示“ Zip…

【智能车Code review】——环岛的判定与补线操作

博主联系方式: QQ:1540984562 QQ交流群:892023501 群里会有往届的smarters和电赛选手,群里也会不时分享一些有用的资料,有问题可以在群里多问问。 视频讲解 这里是对于代码的讲解视频,大约一个小时,需要的同学可以看看:B站:meeting_01 系列文章 【智能车Code review】…

Python交换两个变量的三种方法

一、借助于第三个变量(很常用) a 5 b 6c 0 c a a b b c print("a%d,b%d"%(a,b))#结果为:a6,b5二、如何不借助第三个变量实现两个变量交换数据呢? a 5 b 6a ab b a-b a a-b print("a%d,b%d"%(a,b))#结果为:a…

linux下怎么查kill某个进程,Linux下查询进程PS或者杀死进程kill的小技巧

假设我们要kill掉tomcat:那么我们首先需要tomcat的进程号pid:ps -aux | grep tomcat记下tomcat的PID后,执行:kill PID(tomcat)好了,就到这里....路人甲:小的们,灭了这个欺骗人民情感的家伙&…

【笔记】VB控件MSComm功能介绍

VB中的MSComm 控件通过串行端口传输和接收数据,为应用程序提供串行通讯功能。MSComm控件在串口编程时非常方便,程序员不必去花时间去了解较为复杂的API函数,而且在VC、VB、Delphi等语言中均可使用。 Microsoft Communications Control&#x…

string charat_Java String charAt()方法与示例

string charat字符串charAt()方法 (String charAt() Method) charAt() method is a String class method in Java, it is used to get the character from specified index from a given string. charAt()方法是Java中的String类方法,用于从给定字符串的指定索引中获…

opencv模板匹配

matchTemplate函数参数 模板匹配是通过模板在采集到的原图像进行滑动寻找与模板图像相似的目标。模板匹配不是基于直方图的方式,而是基于图像的灰度匹配。 6种匹配度量方法: 平方差匹配法CV_TM_SQDIFF 归一化平方差匹配法CV_TM_SQDIFF_NORMED 相关匹配…

Java程序设计4——集合类

1 JAVA集合概述 Java集合封装了一系列数据结构比如链表、二叉树、栈、队列等,然后提供了针对这些数据结构的一系列算法比如查找、排序、替换,使编程难度大大降低。(这句话有可能是非法…

Python中的a+=a和a=a+a的区别(认真看完后,我相信你一定会回来感谢我的)

一、先来两段代码! a 100def beyond(num):numnumprint(num)beyond(a)#结果为:200 print(a)#结果为:100a 100def beyond(num):numnumnumprint(num)beyond(a)#结果为:200 print(a)#结果为:100通过这两段代码的结果可以…

安装linux后win7引导程序,安装Windows7+Ubuntu+CentOS三系统之后的引导问题

依次安装了Windows7、Ubuntu12.04、CentOS6.3系统后,开机引导项只有CentOS和Other(即Windows7)两个选项,无法进入Ubuntu系统,所以利用Ubuntu的LiveCD光盘启动后进行如下操作对grub进行修复,步骤如下:启动Live CD&#…

Web之神php

我开始学习做网页的时候用的是asp,后来转行用php。以前只知道php很好学,并且很方便。我学习php的时候关于php的书种类很少好像那时候我在当当上面只看到3本,跟现在没法比,现在大家再学习php就简单多了,那么多书那么多资料。 现在我…