转自: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 的区位码规则,来解析这些文字,并显示在屏幕上,于是乱码产生了,所以说,其实本没有乱码,只不过,鸡同鸭讲时,彼此都听不明白而已。
相关推荐
### 字符编码概述 字符编码是信息技术领域的一个重要概念,涉及到如何将人类可读的文本转换成计算机能够处理的形式。本文旨在深入探讨字符编码的基本原理及其常见类型,以帮助读者理解不同编码方式的特点和应用场景...
Unicode是一种广泛使用的字符编码标准,它旨在解决早期多种编码系统并存导致的兼容性问题。本篇文章将深入探讨文字编码的基本概念,以及Unicode在现代计算中的重要地位。 首先,让我们理解一下基本的文字编码。早期...
《浅谈文字编码和Unicode》这篇文章深入探讨了文字编码与Unicode的概念,以及它们在实际应用中的运作机制。Unicode是一种全球性的字符编码标准,旨在统一世界上所有语言的文字编码,以解决不同编码间的兼容性问题。...
首先,"浅谈C中的wprintf和宽字符显示2008.doc"这篇文章可能探讨了C语言中的宽字符处理,特别是`wprintf`函数。`wprintf`是C语言标准库中的一个函数,用于格式化并打印宽字符字符串,它是`printf`函数的宽字符版本。...
- **代码页**: 代码页是一种特定的字符编码方案,用于定义一组特定字符集的编码方式。例如,代码页936对应简体中文的GBK编码,而代码页950则对应繁体中文的Big5编码。 - **ANSI代码页**: 在Windows中,ANSI代码页...
ASCII码是最初的字符编码标准,主要用于表示西欧语言,但对非英文字符支持不足。为了处理多字节字符,如汉字,国标码(GB系列)被引入,但它们不是计算机内部直接使用的代码,而是通过汉字内码(如GBK)来实现。当...
在编程语言JavaScript中,字符编码转换是一个重要的基础知识点。字符编码是字符在计算机内部存储和处理的规则,不同的编码方式决定了字符占用的字节数和表达方式。在处理字符串数据时,了解和掌握字符编码转换的方法...
有时候,我们需要在页面中使用一些特殊的字符或图标,以增强用户体验或者传达特定信息。本文将探讨如何在HTML和CSS中处理这些特殊字符。 首先,HTML提供了许多预定义的特殊字符实体,这些实体可以帮助我们插入非...
项目中用到的一些特殊字符和图标 html代码 XML/HTML Code复制内容到剪贴板 <div u00a0class=cross></div> css代码 CSS Code复制内容到剪贴板 .cross{ width: 20px; height: 20px; background-color:...
"浅谈程序设计竞赛的算法知识-罗勇军1" 本文浅谈程序设计竞赛的算法知识,作者罗勇军从华东理工大学,发表于2019年7月30日。文章讨论了程序设计竞赛的算法知识,包括Ad Hoc、Complete Search、Divide and Conquer、...
Unicode是一个致力于统一全世界所有字符的字符编码标准,由Unicode联盟维护。它的核心思想是创造一个统一的字符集,使得每一个字符都能被编码进这个集合中,从而解决计算机中字符编码不统一的问题。Unicode为每个...
2. 代码排版:在JavaScript编码中,每行代码长度应控制在80个字符以内,超过这一长度时应当适当换行。为了保证代码的可读性,新的代码行应该使用8个空格的缩进来对齐,而与代码段整体的缩进区分开来,通常代码段使用...
"浅谈JAVA编写系统中文显示问题及其处理.pdf" JAVA 编写系统中文显示问题是指在使用 JAVA 语言进行系统编程时遇到的中文显示乱码问题。这些问题包括浏览器页面乱码、表单数据提交时的乱码、数据库中信息不能正确...
JavaScript编码规范是保证代码质量和可读性的重要指南,尤其对于广泛应用于Web开发的JavaScript语言,良好的编码习惯至关重要。本文将探讨几个关键的编码规范方面,包括文件引用、代码排版、命名规则、变量声明、...