“在QQ聊天窗口按住Alt键,接着用小键盘输入‘29482’,松开Alt后就会看到你的名字了!”收到好友发来的消息,忍不住试了一下,结果自己的名字就成了“猪”。虽然只是一个玩笑,但你难道不想知道人为什么会变“猪”吗?
小实验:向MM表白的经典方案
试着在QQ的聊天窗口中按住Alt,然后通过小键盘依次输入73、76、85、90641、94769、85856。这就是说,能够用这种方法输入的不仅有“猪”,所有的文字都可以。怎么把喜欢的MM的名字变成代码?接着往下看吧!
汉字或其他字符都可以通过按住Alt+小键盘数字的方式输入,而且它们和数字是一一对应的关系。要找出这种对应关系,就需要先了解计算机的字符编码规则。
文字是如何输入和显示出来的
1.不认图只认数
我们知道计算机所认识的数字只有两个,即0和1,不同0、1组合组成二进制数字,这些二进制数字可以转换为八进制、十进制或十六进制的数字。我们在显示器上看到的文字对计算机而言其实是一种不认识的图形,计算机是不能直接处理图形的,所以我们需要将文字的图形保存在电脑的存储器中,然后操作系统中制定一个对应的规则让文字图形和数字逐一对应。其中,文字图形的集合就是我们的字体库,而对应的规则就是文字编码了。
2.编码和解码
当我们通过输入法输入文字后,系统核对文字图形后根据文字编码规则将文字信息转换成为十六进制的数字代码,然后变成计算机可以处理的二进制代码,这就是文字的编码过程。
当计算机处理完文字信息后,以二进制数字代码表示的结果需要转换为十六进制的数字,这时系统将通过根据一定的文字编码规则到字体库中查找数字代码所对应的文字图形,然后显示在屏幕上,这样就能够在屏幕上看到该文字,这就是文字解码。
也就是说,在文字输入到显示在屏幕需要经过两个过程——编码和解码,在编码和解码的过程中都需要通过文字编码规则,于是就产生这样的疑问,编码和解码过程中的文字编码规则是不是一样的呢?
战国风云录!从ASCII到Unicode
1.翻倍后的扩展ASCII
人类的语言是相当丰富的,不同国家甚至民族所使用的文字有很大的区别,所以产生了许多不同的文字编码。最初的时候,人们收录了字符并按照一定规则组成了一个字符编码集合——ANSI(即美国国家标准化组织,各项国际标准的制定者,包括ANSI文字编码标准)的ASCII码(美国信息交换标准代码),它使用7位(Bits)来表示一个字符,如字符“a”的ASCII码为1100001,这样共能表示2的7次方(即128)个字符,其中包括了英文字母、数字、标点符号等常用字符。后来为了能表达更多字符,人们又将其进行了扩展,使用8位表示一个字符,共能表示256个字符(2的8次方),主要在原来的7位字符集的基础上加入了一些特殊符号,扩展ASCII码向下兼容原来的ANSI ASCII码。
2.扩展了还是不够
随着计算机的普及,而ASCII最多能只能表达256个字符集,显然不能满足需求了(中文的常用汉字就有几千个,区区256实在是……)。为了能表示各国文字,各国在ASCII的基础上制定了自己的字符集,这些以ASCII为基础派生字符集,我们称之为多字节字符系统(Multi-Byte Chactacter System,简称MBCS),使用大于128的编码作为一个引导字节(Leading Byte),紧跟在引导字节后的第二(甚至第三)个字符与引导字节一起形成新的文字编码。这样的字符集有很多,我们常见的GB2312、Big5、Shift-JIS、IS08859等编码。
3.“字符集冲突”的拯救者
由于每种语言都制订了自己的字符集,导致最后存在的各种字符集实在太多,甚至中文的简繁体之间字符集也不同,十分不便(比如玩繁体字游戏时就会出现乱码,必须使用“南极星”等内码转换工具)。为了方便信息交流,人们又重新收录了字符集——Unicode,它为所有字符都分配了一个惟一对应的编码,这样的编码无须考虑平台、程序、语言的区别,在Unicode内核的平台上中都能正常显示。也就是说Unicode编码收集了人类几乎所有语言的字符信息,所以Unicode编码还可称为通用文字编码。此外,Unicode编码中包含了单、双甚至多字节的字符,于是Unicode可以细分为多种编码形式,常见的有UTF-7、UTF-8、UTF-16和UTF-32,这些编码都属于Unicode字符集。
[Page: ]
小资料:Unicode的前世今生
历史上存在两个试图独立设计Unicode的组织,即国际标准化组织(ISO)和一个软件制造商的协会(unicode.org)。ISO开发了ISO-10646项目,也称为UCS,而Unicode协会开发了Unicode项目。其中ISO-10646的Code Space(编码空间)为U+0000—U+10FFFF,而Unicode的Code Space为U+0000—U+FFFF,这就是Unicode1.0,也是我们平时说的Unicode。后来双方都认识到人类并不需要两个不兼容的通用字符集,于是两个组织合并双方的工作成果,并为创立一个单一编码表而协同工作,于是诞生了Unicode2.0。从Unicode2.0开始,Unicode项目采用了与ISO 10646-1相同的字库和字码。
多变的系统内码
1.从ANSI往Unicode跑的Windows
操作系统内部的文字编码就是内码,在早期的Windows 9x操作系统中,系统的所采用的默认编码是与语言相关的。为了让操作系统可以支持全世界所有的语言文字,后来的Windows 2000/XP等采用的都是通用文字编码——Unicode字符编码。
2.见人说人话,见鬼说鬼话
现有的大量程序和文档都采用了某种特定语言的编码来编写,例如GBK、BIG5、GB2312等,举一个简单的例子:在GBK编码中“汉字”的对应码为“BABAD7D6”,如果用“记事本”打开包含“汉字”的GBK编码文本,Windows应该怎么解释“BABAD7D6”这串字节流呢?是按照Unicode编码解释、还是按照GBK或者BIG5去解释?最理想的方式是按GBK去解释,并得到“汉字”两个字,但也有可能按照其他编码解释,可能找不到对应的字符,或是找到错误的字符(所谓“错误”是指与文本作者的本意不符,产生了乱码),如何避免系统出现乱码呢?
这就涉及一个代码页(Code Page)的概念,也就是当系统启动某些非系统内码编写的程序时,系统指定用来解释该程序的文字编码,通常这个代码页是为了让程序能更好地适应特定的语言环境而设计的,不同操作系统编码也是有所不同的,在简体中文的Windows中,代码页有CP20936、CP54936等,代表文字编码分别为GB2312、GB18030,可以通过“控制面板→区域和语言选项”设置和查询缺省代码页(见图1)。
你也可以变魔术
1.教你查编码
回到原来的话题,来看看人到底是如何变成“猪”的。按前文所述,“猪”字和数字“29482”是一个对应关系,很显然29482是一个10进制的数字,“猪”字的Unicode编码用十进制数字表示就是29482。
依次打开“开始→程序→附件→TrueType 造字程序”命令,选择一个代码后打开造字窗口,然后在主窗口中选择“窗口→参照”命令,打开“参照”窗口。在“形状”中输入“猪”字,接着在“代码”中显示的结果为“732A”(见图2)。运行calc.exe打开“计算器”,选择菜单“查看→科学型”,选择“十六进制”后键入“732A”,再选择“十进制”后十六进制代码就转换为了十进制,结果正好是“29482”(见图3)。
小提示
通过上面的方法就能查出所需字符的内码数字,如果嫌麻烦,可以从http://work.newhua.com/cfan/200611/AltInput.rar下载一个快速转换工具。
[Page: ]
2.为何魔术的结果有差异
细心的读者可能发现,在QQ聊天窗口中与其他文本输入窗口中,ALT+小键盘的“29482”的结果是不尽相同的,比如系统自带的记事本中得到的是“s”,这是为什么呢?这是因为“记事本”默认的文字编码不是Unicode编码造成的,它默认采用了Windows代码页所指定的文字编码,在简体中文的Windows系统中即为GB2312编码。也就是说,在记事本中,我们通过ALT+小键盘的“29482”所输入到记事本中的信息采用的是Unicode编码,但记事本却用GB2312编码来解释,解释出来正好得到s(小写)。
使用Ultraedit打开“记事本”保存的包含“猪”字的文本文件,切换到十六进制下可以看到“猪”字的GB2312编码是D6ED。选择菜单“文件→转换→ASCII转Unicode”,可以看到“猪”的Unicode编码是“FFFE2A73”,而窗口右侧显示的GB2312编码的“?s”(见图4)。注意,其中“FFFE”为UTF-16/Big Endian编码的特征字符,而“2A73”才是“猪”字真正的Unicode码。
3.吃大头还是吃小头
猪的Unicode编码是“732A”,为什么在UltraEdit中却是“2A73”呢?要揭开这个谜团,得先了解什么是Big-endian和Little-endian。Big-endian和Little-endian是CPU处理多字节字符所采用的不同方式,Big-endian即高位数放在前(头字节特征为FEFF),和数字的书写习惯一样,而Little-endian是高位放在后面(头字节特征为FFFE)。“Endian”这个词出自《格列佛游记》。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开,由此曾发生过六次叛乱,其中一个皇帝送了命,另一个丢了王位。