关于字符集的学习笔记

大家知道,在计算机中,数据都是以二进制的形式来表示的,只有 0 跟 1。而我们在电脑屏幕上看到的能够被我们所理解的这些都是字符,不管是中文也好,英文也好,它们被存储到计算机内部的时候,都会被转换成二进制。

那用什么样的二进制来显示什么样的字符呢,这就是由人们来决定了,这就是所谓的编码。

也正因为此,出现了各种各样的编码方式,比如ASCII,UNICODE,还有和我们汉字相关的GB2312和GBK等。

ASCII

ASCII码是大家最熟悉的一种编码方式了,是在上个世纪60年代(1961年)由美国制定的一套标准,原来是美国的国家标准,后来被ISO定为国际标准,在今天,所有的机器上都支持ASCII编码集。

ASCII码基本上是对英文字母和二进制的编码转换,它共由7位二进制位表示,因此其一共能表示128个字符,其中0~31 是控制字符(不能打印出来),还有96个可以打印出来的字符,包含数字,大小写英文字母和一些标点符号等。

但是由于计算机存储的基本处理单位为字节(Byte),也就是8位,所以一般会以一个字节来存储ASCII码,那么最高位就会置0。

从上表,我们可以看到,ASCII码仅支持英文,如果全世界通行的语言就只有英文,那就简单了,也就不会有那么字符编码格式了,但是很可惜,事实上不是这样的。

世界的多元化发展,造就了多姿多彩的语言,比如现在我们大家都看到的汉字,对吧。

每一个汉字就像每一片树叶,都是独一无二的。那么仅仅有128种状态的ASCII码表,是没有办法来满足汉字的表达的。

于是有一些西欧国家,就决定利用ASCII码中的闲置的最高位,这样的,利用8位编码,它们能够表示256种状态,也就是说他们能够利用扩展的ASCII码来表示256个字符。

对于这一些以拉丁字母为主的西欧国家,256个字符是足够的。

但是却存在一个问题,不同的国家,原来的0-127个ASCII码,大家都保持不变,还是统一的,但是在128-255这一段的编码都是按照自己国家的语言来表示,就会出现这样一个问题:

同样的编码,在不同的国家,显示为不同的字符。

在互联网还不普及,全球化交流没那么频繁的时候,这种缺陷还不明显,但是在当今这个时代显然是不能拉受的。

因为计算机显示任何一种字符,都必须要先知道对应的编码方式,否则就会显示乱码了。

另外,对于我们亚洲国家,尤其是汉字来说,256个字符还是远远不够的!

ANSI编码和MBCS

于是为了显示本国的语言,不同的国家和不同的地区分别制定了不同的标准,于是就产生了诸如GB2312(简体中文字符集),BIG5(繁体中文字符集)等各种不同的编码标准。

由于汉字远远不只256个字符,所以这些编码方式都采用了2字节的编码方式,在Windows系统上一般称之为ANSI编码(Windows-1252),也称为多字节字符集(MBCS, Multi-Bytes Character Set)。

这是针对Windows系统的,在中文Windows操作系统下,ANSI编码就是GB2312编码,而在日文操作系统下,ANSI编码就是JIS编码。

但是不同的ANSI编码是没有办法互相转换的,谁也不认识谁。

于是我们又回到了之前的一个问题,在当今这个全球化的时代,我们必须有一个统一的字符集能够包含所有的字符。

Unicode

Unicode,我想应该是universal code的合拼,它表明就是整个宇宙所有的编码都会包含在这里面,当然,目前也就是地球而已,不包含火星文。

Unicode将目前世界上通用的所有的字符都收纳了进来,为每一个字符分配了一个唯一的Unicode,比如U+4E00就是汉字的“一”,通过UltraEdit等工具,我们可看看其保存为UTF-16时的编码格式如下:

我们是将文件保存为UTF-16的编码格式的,那么UTF-16和Unicode有什么关系呢,上面内容显示的“FF FE”又是表示什么意思呢?

在这里,我们首先要明确一点, 那就是Unicode只是一个字符集,它只定义了在Unicode中,一个符号其对应的16进制是什么,比如上面汉字的“一”,其对应的Unicode就是4E00,除此之外,它不干其他事情。

为什么Unicode不定义字符的存储结构呢?

我觉得主要原因在于资源的存储和传输的问题,比如对于ASCII码里面的英文字母,它们当然也包含在Unicode中,如果Unicode统一规定了一个字符要用多少个字节来存储,那么很显然肯定不只能用一个字节,因为除了英文字母,

还有其他语言字符。那如果用2个或者更多个字节,ASCII码又用不了这么多,每次存储都要用好多的00000在前面,这多浪费资源,传输起来也会有效率的问题。

很显然,这就决定了会有多种Unicode的存储方式,比如我们上面讲到的UTF-16,其他的还有我们经常用到的UTF-8,还有UTF-32等。

偶尔,我们还会看到UCS-2和UCS-4,它们跟Unicode有什么关系呢?其实Unicode字符集,就是叫做Unicode字符集,英文也就是 Unicode Character Set,即UCS,那么UCS-2就是表示用两个字节,也就是16位来表示的Unicode了。

但是要注意一点,基于维基百科,UTF-16是用来取代UCS-2的。

UCS-2表示的Unicode中从U+0000到U+FFFF这段范围的字符,但是在这段字符中,U+D800到U+DFFF是作为无字符来保留的,而UTF-16,则是利用了这段保留位置保存了位于U+010000到U+10FFFF的字符集。

所以,虽然两者都是只能表示2^16个字符,但其范围是不一致的。

至于UCS-4,就是UTF-32是一样的了。

说到这里,相信大家,也就清楚了,其实UTF-16,也就是一种对Unicode的实现方式,只是它对于Unicode中U+0000到U+FFFF这段字符的存储格式的实现。

而由于都是两个字节,所以基本上Unicode的值是什么,UTF-16的实现也就是什么值,以致于很多情况下人们把Unicode跟UTF-16都划上等号了,其实,它们一个是定义,一个是实现的存储方式。

因为正好是两个字节,那么计算机到底将哪个字节保存在前,哪个字节保存在后呢?都是可以的,这就涉及到一个字节序的问题了。

字节序

字节序也称之为Byte Order Mark,也就BOM,就是上面保存形式中的FF FE了,这是Unicode规范中的推荐方法。

Unicode字符中,定义了这样一个字符串,U+FEFF,叫做“zero-width non-breaking space”。在存储字符前,添加这样一个BOM,来表明编码的顺序,告诉CPU应该先存高字节,还是低字节。

Little Endian: 一般叫小尾,添加FF FE,表明是反过来存储,先存低字节(后面的字节),再存高字节(前面的字节),比如汉字的“一”,其Unicode值为U+4E00,则如果选择UTF-16(Little Endian)在存储方式,则就会是上图中的存储了。

Big Endian:一般叫大尾,会在字符前面添加FE FF,正好反过来,按顺序先保存高字节,再保存低字节,存储为FE FF 4E 00了,如下图所示。

上面所述的,一般就是UTF-16的存储方式,但其限定了固定两个字节的存储方式,而UTF-8,则是以一种变长的存储方式,慢慢地变成互联网上最流行的一种字符存储和传输方式。

UTF-8

UTF-8,可以使用1-4个字节来表示一个符号,其编码规则如下:

对于单字节的符号,第一位设为0,后面的七位设置为其Unicode值,也即是ASCII码了。

对于n(n > 1)字节的的符号,第一个字节的前n位设置为1,第n+1位设置为0,而接下来每个字节的前两位固定为10,之后将该符号对应的unicode值的二进制位按顺序填充剩下的位数。

具体形式如下:

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

根据这个表格,我们可以看看汉字“一”,变成UTF-8编码的值为多少。

其Unicode值为4E00,其范围在0000 0800 - 0000 FFFF这个区间,可见其是要用三个字节来编码的,其二进制为0100 1110 0000 0000,则可知其UTF-8的二进制为1110 0100 1011 1000 1000 0000,转化为16进制为 E4 B8 80 00,接下来让我们将上面的“一”字保存成UTF-8格式吧

结果如上图所示,那么EF BB BF又是什么呢?

UTF-8是以8位为单元对Unicode进行编码的,所以其是以字节为单位来编码的,那么就不存在什么字节序的问题了,而EF BB BF其实是对FE FF的编码来的。

既然不存在字节序的问题了,为什么还要在前面添加这个BOM呢?

这是因为,可以利用这个BOM来表明编码方式,当接收到EF BB BF开头的字符串的时候,我们就知道后面的字符串是以UTF-8编码的。

好了,结束!

关于字符集的学习笔记

时间: 2024-08-25 13:47:16

关于字符集的学习笔记的相关文章

mysql字符集学习笔记分享

接着上一篇继续来一篇关于mysql字符设置等问题学习笔记,这篇就不说什么废话了,直接进入正题,不过还是感谢十八哥的无私分享! 我们首先看看mysql整个数据存储和读取一个流程: 连接器(connection) 特性:链接客户端与服务器 过程: 客户端的字节先发给连接器,   连接器选择一种编码将其转换,临时存储 再次转换成 服务器西药的编码,并正真的存储在服务器上 现在,我们以mysql这个流程说一下,在存入数据和读取数据时的编码转换. 如图 存入数据: 读取数据: A:client:GBK -

Java NIO、NIO.2学习笔记

相关学习资料 http://www.molotang.com/articles/903.html http://www.ibm.com/developerworks/cn/education/java/j-nio/j-nio.html 目录 1. NIO.NIO.2简介 2. NIO中的关键技术 1. NIO.NIO.2简介 Java中的输入流.输出流都是阻塞式的输入.输出.不仅如此,传统的输入流.输出流都是通过字节的移动来处理的(即使是字符流,在底层也是通过字节流来进行处理的),也就是说,面向

关于ASCII、GB231、GBK、UTF-8/UTF8、ANSI、unicode的学习笔记

继续上次的学习内容,写一些自己学习的笔记吧!总是觉得没有笔记的学习总是不那么踏实,我承认自己是个记忆力很差的人,特别羡慕那些可以把自己学过的东西记得很牢靠的人.哎!可惜我不是,那只能做出来点东西,就算以后忘了,回过头来可以看一看,有东西查:毕竟是自己亲手打出来的一个一个字啊 已经一万六千字了!嘿嘿...继续加油! 今天公司网络有问题,说是让在家里上班,skype在线就行了.结果我这自觉性不够,就打酱油了!还是继续学习我的mysql吧!我是刚毕业的大学生,学的和写的都是一些最基础的,如果巧遇大牛,

Struts2.X深入浅出 学习笔记

第一节.MVC以及Struts2简介 第二节.Action生命周期以及接收表单数据 第三节.Struts2配置以及Struts.xml详解 Struts2 主要配置文件 ? 1 2 3 4 5 Web.xml 设置过滤器以及annotation初始化参数 Struts.xml 主配置文件 Struts.properties 默认属性文件 Struts-default.xml 默认配置文件 Struts-plugin.xml 插件配置文件 Struts2 主要配置加载次序 ? 1 2 3 4 5

oracle入门学习笔记

Oracle学习笔记 推荐书籍:<Oracle有用教程(从入门到精通)>.<深入浅出Oracle> 1. 当前主流数据库: |-微软:SQL Server.access |-瑞典:Mysql |-IBM: DB2 |-Sybase: Sybase |-Oracle:Oracle A. 小型数据库:access.foxbase. 负载量小,100人内,成本千元内,安全性要求不高. 比如留言板等. B. 中型数据库:Mysql.SQL Server.Informix.日訪问量5000-

(转)两千行PHP学习笔记

亲们,如约而至的PHP笔记来啦~绝对干货! 以下为我以前学PHP时做的笔记,时不时的也会添加一些基础知识点进去,有时还翻出来查查. MySQL笔记:一千行MySQL学习笔记http://www.cnblogs.com/shockerli/p/1000-plus-line-mysql-notes.html //语法错误(syntax error)在语法分析阶段,源代码并未被执行,故不会有任何输出. /* [命名规则] */ 常量名 类常量建议全大写,单词间用下划线分隔 // MIN_WIDTH 变

HTML 学习笔记 day one

HTML学习笔记 day one Chapter one 网站开发基础 1.2网站的基本架构 网站的基本要素:内容,页面,超链接 动态网页和静态网页的区别在于:动态网页会自动更新,后缀名是.asp或者.aspx;而静态网页不会自动更新,要改变它只能够去改变它的代码,它的后缀名是.html或者.htm. 1.3常见的网站结构 苹果mac os x 平台的web浏览器是Safari,Firefox是最符合web标准的浏览器(现在的设计师检测网站的时候,一般会用IE,Firefox,opera,Saf

Android学习笔记之HttpClient实现Http请求....

PS:最近光忙着考试了....破组成原理都看吐了....搞的什么也不想干...写篇博客爽爽吧....貌似明天就考试了...sad... 学习笔记: 1.如何实现Http请求来实现通信.... 2.解决Android 2.3 版本以后无法使用Http请求问题....   这里我使用HttpClient来开发Http程序来完成简单的网络通信....其实使用HttpUrlConnection也可以实现,不过HttpClient可以完成HttpUrlConnection的所有功能,并且还自己增加了其他的

我的Hook学习笔记

关于Hook 一.基本概念: 钩子(Hook),是Windows消息处理机制的一个平台,应用程序能够在上面设置子程以监视指定窗体的某种消息,并且所监视的窗体能够是其它进程所创建的.当消息到达后,在目标窗体处理函数之前处理它.钩子机制同意应用程序截获处理window消息或特定事件. 钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统.每当特定的消息发出,在没有到达目的窗体前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权.这时钩子函数即能够加工处理(改变)该消息,也能够不作处理而继续传