字符编码

转字刨根究底字符编码

单位


比特Bit(Binary Digit),计算机中信息表示的最小单位。

字节

一连串的位(比特),称为位串(比特串)。
现代个人计算机的存储器编址,一般是按字节为单位,称为按字节编址。

现代计算机用8位来代表一个字节。

字与字长

在计算机中,一串比特位是作为一个整体来处理或运算的,这串比特位称为一个计算机字,简称字。
字通常分为若干个字节。

字长即字的长度,是指计算机中每个字所包含的位数。
字长决定了CPU一次操作所处理的实际比特位是多少。
字长由CPU对外数据通路的数据总线宽度决定。

虽然字节的大多数现代计算机的最小存储单元,但并不代表它是计算机可以最高效地处理的数据单位。

一般来说,计算机可以最高效地处理的数据大小,应该与其字的字长相同。

计算机可以最高效的处理的数据大小,应该与其字的字长相同。

计算机处理数据的速率,显然和它一次能加工的位数以及进行运算的快慢有关。
如果两台计算的速率相同,一台计算机的字长是另一台计算机的两倍,若两台计算机的速率相同,在相同的时间内,前者能做的工作是后者的两倍。(32位和64为操作系统)

字符集


Character Set,字符的集合,是一个自然语言文字系统所支持的所有抽象字符的集合。

常见字符集ASCII、GB2312、GBK、GB18030、BIG5、Unicode字符集。

编码和解码

Encode,是信息从一种形式或格式转换到另一种形式或格式的过程。
Decode,编码的逆过程。

字符编码

把字符集中的字符按一定格式编码为某指定集合中某一对象的过程。例如电子元件不同状态(开和关)能代表数字系统中的数字(0和1)。

ASCII将字母、数字和其它字符进行编号,并且在计算机中直接用7比特的二进制数字来表示这个编号,通常会额外的在最高位再增加一个扩充的比特位”0”,以便于计算机刚好以1个字节的方式来进行处理、存储和传输。

字符编码模型


Character Encoding Model,反映字符编码系统的结构特点和各构成部分相互关系的模型框架。

传统字符编码模型

在传统字符编码模型中,基本上都是将 字符集里的字符进行编号,然后该编号就是字符的编码。

现代字符编码模型

  • 有哪些字符
  • 这些字符的编号是什么
  • 这些编号如何编写成一些列逻辑层面有限大小的数字,即码元序列
  • 这些逻辑层面的码元序列如何转换为物理层面的字节流
  • 在某些特殊的传输环境中(如Email),再进一步将字节序列进行适应性编码处理

层级:

第一层 Abstract Character Repertoire抽象字符清单: 明确字符的范围即确定支持哪些字符

其中的字符并没有编排数字顺序
“抽象”字符不具有某种特定的字形,不应与具有某种特定字形的“具体”字符混淆
字符表可以是封闭的(即字符范围是固定的),即除非创建一个新的标准(ASCII字符表和多数ISO/IEC 8859系列都是这样的例子),否则不允许添加新的符号;字符表也可以是开放的(即字符范围是不固定的),即允许不断添加新的符号(Unicode字符表和一定程度上Code Page代码页是这方面的例子)。

第二层 Code Character Set编号字符集CCS:用数字编号表示字符(用数字给抽象字符表ACR中的字符编号)

将抽象字符的集合映射一个非负整数或非负整数值对(例如x,y坐标系)的集合,映射的结果就是编号字符集CCS。因此,字符的编号也就是字符的非负整数代码。
根据抽象字符集中抽象字符的数目,可以设定一个字符编号的上限值(该上限值往往设定大于抽象字符表中的字符总数),从0到该上限值之间的非负整数范围就称为**编号空间**。
编号空间中的一个位置称为码点(Code Point代码点)或码位(Code Position代码位)。一个字符占用的码点所在的坐标(非负整数值对)或所代表的非负整数,就是该字符的编号,又称为**码点值(即码点编号)**
在Unicode标准中,一个单个的抽象字符,既有可能与多个码点对应(为了与其它标准兼容,比如码点编号为U+51C9与U+F979的这两个码点实际上是同一个字符“凉”,这是为了兼容韩国字符集标准KS X 1001:1998,具体可参看Unicode的官方文档),也有可能使用一个由多个码点所组成的码点序列表示(为了表示由基本字符与组合字符组合在一起所组成的字符,比如à,由码点编号为U+0061的基本字符字母“a”和码点编号为U+0300的组合字符读音符号“̀”组成);同时,也并非每一个码点都对应于一个字符,也存在着非字符码点或保留码点。

这里写图片描述

第三层 Character Encoding Form字符编码方式:将字符编号(即码点值)编码为码元系列(字符编码)

不同于传统的封闭的ASCII字符表,Unicode字符表是一个现代的开放的字符表,未来可能有更多的字符加入进来(比如很多Emoji表情符就被源源不断地加入进来)。因此,Unicode编号字符集所需要的码点数量,必然是会不断增加的,相对来说是无限的。但计算机所能表示的整数范围却是相对有限的。
字符编码方式,是将编号字符集里字符的码点值(即码点编号、字符编号)转换成或者说编码成有限比特长度的编码值(即字符编码)。
在Unicode这样现代的、复杂的字符编码系统中,字符编号不一定等于字符编码,字符编号与字符编码之间不一定是一个直接映射关系(UTF-8、UTF-16为间接映射,UTF-32为直接映射)。

第三层 Character Encoding Scheme字符编码模式:将逻辑上的码元序列映射为物理上的字节序列

也称作"Serialization Format"(序列化格式),是将字符编号进行编码之后的码元序列映射为字节序列(即字节流),以便编码后的字符在计算机中进行处理、存储和传输。
由于硬件平台与操作系统设计上的历史原因,对于UTF-16、UTF-32等采用多字节码元的编码方式而言,必须使用一个原先称之为零宽度不中断空格(ZERO WIDTH NO-BREAK SPACE)的字符(Unicode字符编号为FEFF)来指定字节序(Byte-Order字节顺序、位元组顺序,或称为Endianness端序)是大端序还是小端序,计算机才能够正确地进行处理、存储和传输。
不过,对于**UTF-8**这种采用单字节码元的编码方式来说,并不存在字节序问题,不需要指明字节序。因此,在各种计算机系统平台中,UTF-8编码的码元序列与字节序列都是相同的。

第五层 Transfer Encoding Syntax传输编码语法:将字节序列作进一步的适应性编码处理

由于历史的原因,在某些特殊的传输环境中,需要对上一层次的字符编码模式CES所提供的字节序列(字节流)作进一步的适应性编码处理。一般包括两种:
* 一种是把字节序列映射到一套更受限制的值域内,以满足传输环境的限制,例如用于Email传输的Base64编码或者quoted-printable编码(可打印字符引用编码),都是把8位的字节映射为7位长的数据(Email协议设计为仅能传输7位的ASCII字符);
* 另一种是压缩字节序列的值,如LZW或者进程长度编码等无损压缩技术。

区别

现代字符编码模型核心是创建一个能够用不同方式来编码的通用字符集。

传统字符编码模型中,字符编码方式与字符集是密切结合在一起的,而在现在字符编码模型中,字符编码方式与字符集脱钩了。

ASCII字符编码方案

ASCII码使用七个二进制数字(bit比特、位)来表示一个字符,总共表示128个字符(2^7 = 128,二进制编码为0000 0000 ~ 0111 1111,对应的十进制就是0~127)。
  • 0~31:控制字符或通讯专用字符(不可显示不可打印字符),如0x07(BEL响铃)会让计算机发出哔的一声、0x00(NUL空,注意不是空格)通常用于指示字符串的结束、0x0D(CR回车)和0x0A(LF换行)用于指示打印机的打印针头退到行首(即回车)并移到下一行(即换行)等。
  • 32~126:可显示可打印字符(其中32为可显示但不可打印的空格字符),48~57为0-9的阿拉伯数字,65~90为26个大写英文字母,97~122为26个小写英文字母,其余的是一些标点符号、运算符号等。
  • 127:控制字符DEL。

EASCII

Extended ASCII
当第一个比特位(即字节的最高位)为0时,仍表示之前那些常用的ASCII字符(实际的二进制编码为0000 0000 ~ 0111 1111,对应的十进制就是0~127),而为1时就表示补充扩展的其他衍生字符(实际的二进制编码为1000 0000 ~ 1111 1111,对应的十进制就是128~255)。
EASCII码比ASCII码扩充出来的符号包括表格符号、计算符号、希腊字母和特殊的拉丁符号。

EASCII码目前已经很少使用,常用的是ISO/IEC 8859字符编码方案。该方案与EASCII码类似,也同样是在ASCII码的基础上,利用了ASCII的7位编码所没有用到的最高位(首位),将编码范围从原先ASCII码的0x00~0x7F(十进制为0~127),扩展到了0x80~0xFF(十进制为128~255)。
ISO/IEC 8859字符编码方案同样是单字节编码方案,也同样完全兼容ASCII。
ISO/IEC 8859是一组字符集的总称,其下共包含了15个字符集,即ISO/IEC 8859-n,其中n=1,2,3,...,15,16(其中12未定义,所以共15个)。
这15个字符集大致上包括了欧洲各国所使用到的字符(甚至还包括一些外来语字符),而且每一个字符集的补充扩展部分(即除了兼容ASCII字符之外的部分)都只实际使用了0xA0~0xFF(十进制为160~255)这96个编码。

简体汉字编码

GB类的字符集均属于双字节字符集DBCS(Double Byte Character Set)。

当计算机被引入到中国后,相关部门设计了GB系列编码(“GB”为“国标”的汉语拼音首字母缩写,即“国家标准”之意)。
按照GB系列编码,在一段文本中,如果一个字节是0~127,那么这个字节的含义同ASCII编码,否则,这个字节和下一个字节共同组成汉字(或是GB编码定义的其他字符)。
因此,GB系列编码向下兼容ASCII,也就是说,如果一段用GB编码文本里的所有字符都在ASCII中有定义(即该文本全部由ASCII字符组成),那么这段编码和ASCII编码完全一样。
正因为不得不使用多个字节来表示一个字符,相较于只使用单个字节的ASCII编码方案,GB类编码方案与后面要介绍的Unicode编码方案一样,无疑导致了更高的复杂度。

当多字节字符与原先的ASCII字符混用时:
* 要么将原先的ASCII字符重新编码为多个字节表示,以便与其他多字节字符统一起来(UTF-16、UTF-32等采用的是这种方法);
* 要么保持ASCII字符为单个字节编码不变,但将其他多字节字符编码中的各个字节的最高位(首位)设为1,以避免与字节最高位为0的ASCII编码相冲突(GB、UTF-8等采用的是这种方法)。

前者具有更高的空间复杂度,因为原先只需要单个字节表示的ASCII字符,现在也必须用多个字节来表示,显然更为耗费存储空间;后者则具有更高的时间复杂度,因为为了避免冲突以及其他种种考虑(比如扩展性、容错性等),使用了更为复杂的编码算法(encodingalgorithm),无疑更为耗费计算时间。

GB2312

规定表示一个汉字的编码(即汉字内码)的字节其值必须大于127(即字节的最高位为1),并且必须是两个大于127的字节连在一起来共同表示一个汉字(GB2312为双字节编码),前一字节称为高字节,后一字节称为低字节;而一个字节的值若小于127(即字节的最高位为0),自然是仍表示一个原来的ASCII字符(ASCII为单字节编码)。

全角字符

ASCII中的西文字符由于在外观视觉上仅占用半个汉字的视觉空间(主要是宽度),并且在内部存储上使用1个字节进行存储,相对于全角字符,因而被称之为半角字符。
让西文字母、数字和标点等特殊字符在外观视觉上也占用一个汉字的视觉空间(主要是宽度),并且在内部存储上也同汉字一样使用2个字节进行存储的方案。这些与汉字在显示宽度上一样的字符就被称之为全角字符。

GBK

GBK跟GB2312一样是双字节编码,然而,GBK只要求第一个字节即高字节是大于127就固定表示这是一个汉字的开始(0~127当然表示的还是ASCII字符),不再要求第二个字节即低字节也必须是127号之后的编码。这样,作为同样是双字节编码的GBK才可以收录比GB2312更多字符。

CJK指的是中日韩统一表意文字

CJK是中文(Chinese)、日文(Japanese)、韩文(Korean)三国文字英文首字母的缩写。顾名思义,它能够支持这三种文字,但实际上,CJK能够支持包括中文(包含壮文)、日文、韩文、越文在内的多种亚洲双字节文字。

ANSI

所有这些各个国家和地区所独立制定的既兼容ASCII又互相不兼容的字符编码,微软统称为ANSI编码。
在Windows系统的编码处理中,ANSI编码一般代表系统默认编码方式,而且并不是确定的某一种编码方式。

代码页(Code Page)

代码页也称为“内码表”,是与特定语言的字符集相对应的一张表。操作系统中不同的语言和区域设置可能使用不同的代码页。
代码页是字符集的具体实现,可以将其理解为一张“字符-字节”映射表,通过查表实现“字符-字节”的翻译。
代码页主要用于字符在计算机中的存储和显示,比如,计算机读取了一个二进制字节,那这个字节到底代表哪个字符,就需要到指定的代码页中查找,这个查找的过程就被称为查表。

区位码 国标码 内码

区位码

GB2312将包括汉字在内的所有字符编入一个94*94的二维表,行就是“区”,列就是位。每个字符由区、位唯一定位,其对应的区、位编号合并就是区位码。

国标码

为了避开ASCII字符中的不可显示字符和空格字符(0~32),国标码相当于将区位码向后偏移了32。

国标码中是分别将区位码中的“区”和“位”格子加上32(20H),应为GB2312是DBCS双字节字符集,“区”和“位”各作为一个独立的字节。

内码

为避免与ASCII码冲突,规定国标码中的每个字节的最高位都从0换成1,即相当于每个字节都再加上128(十六进制为80,即80H;二进制为1000 0000),从而得到国标码的“机内码”表示,简称“内码”。

总结

从区位码(国家标准定义) —> 区码和位码分别+32(即+20H)得到国标码 —> 再分+128(即+80H)得到机内码(与ACSII码不再冲突)。

因此,区位码的区和位分别+160(即+A0H,32+128=160)可直接得到内码。用十六进制表示就是:

区位码(区码,位码) + (20H,20H) + (80H,80H) =区位码(区码,位码) + (A0H,A0H) = 内码(高字节,低字节)

为什么要加上20H和80H

当时在制定GB2312时,决定对ASCII中的可打印字符,也就是英文字母、数字和符号部分(33~126,127为不可打印的DEL)重新编入GB2312中,以两个字节表示,称之为全角字符(全角字符在屏幕上的显示宽度为ASCII字符的两倍,后来也因此而将对应的ASCII字符称之为半角字符)。

外码(输入码)

英文字母只有26个,可以把所有的字符都放到键盘上,而使用这种办法把所有的汉字都放到键盘上,是不可能的。所以汉字系统需要有自己的输入码体系,使汉字与键盘能建立对应关系。

常用外码

  1. 数字编码(例如区位码)
  2. 拼音编码 (全拼、双拼、自然码)
  3. 字形编码 (五笔、表形码、郑码)

字形码

字形码,又称为字型码、字模码、输出码,属于点阵代码的一种。

为了将汉字在显示器或打印机上输出,把汉字按图形符号设计成点阵图,就得到了相应的点阵代码(字形码)。

也就是用0、1表示汉字的字形,将汉字放入n行*n列的正方形(点阵)内,该正方形共有n^2个小方格,每个小方格用一位二进制表示,凡是笔划经过的方格值为1,未经过的值为0。

显示一个汉字一般采用16×16点阵或24×24点阵或48×48点阵。已知汉字点阵的大小,可以计算出存储一个汉字所需占用的字节空间。

比如,用16×16点阵表示一个汉字,就是将每个汉字用16行,每行16个点表示,一个点需要1位二进制代码,16个点需用16位二进制代码(即2个字节),共16行,所以需要16行×2字节/行=32字节,即16×16点阵表示一个汉字,字形码需用32字节。

因此,字节数=点阵行数×(点阵列数/8)。

为了将汉字的字形显示输出或打印输出,汉字信息处理系统还需要配有汉字字形库,也称字模库,简称字库,它集中了汉字的字形信息。

字库按输出方式可分为显示字库和打印字库。用于显示输出的字库叫显示字库,工作时需调入内存。用于打印输出的字库叫打印字库,工作时无需调入内存。

字库按存储方式也可分为软字库和硬字库。软字库以文件的形式存放在硬盘上,现多用这种方式。硬字库则将字库固化在一个单独的存储芯片中,再和其它必要的器件组成接口卡,插接在计算机上,通常称为汉卡。这种方式现已淘汰。

总结

可以这样理解,为在计算机内表示汉字而采取统一的编码方式所形成的汉字编码叫内码。为方便汉字输入而形成的汉字编码为外码,也叫输入码。为显示输出和打印输出汉字而形成的汉字编码为字形码,也称为字模码、输出码。

计算机通过键盘输入的外码(重码时还需附加选择编号)对应于汉字内码,将汉字外码转换(即映射)为汉字内码,以实现输入汉字的目的;通过汉字内码在字模库(即字库)中找出汉字的字形码,将汉字内码转换(即映射)为汉字字形码,以实现显示输出和打印输出汉字的目的。

事实上,英文字符的输入、处理和显示过程大致上也差不多,只不过英文字符不需要输入码(即外码),直接在键盘上输入对应的英文字母即可。这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值