【转】刨根究底字符编码之六——简体汉字编码中区位码、国标码、机内码、外码、字形码的区别及关系

GB2312、GBK、GB18030等GB系列汉字编码方案的具体实现方式是怎样的?区位码是什么?国标码是什么?内码、外码、字形码又是什么意思?它们是如何转换的,又为什么要这样转换?

下面以GB2312为例来加以说明。

 

一、区位码

1.

整个GB2312字符集分成94个区,每区有94个位,每个区位上只有一个字符,即每区含有94个汉字或符号,用所在的区和位来对字符进行编码(实际上就是码点值、码点编号、字符编号),因此称为区位码(或许叫“区位号”更为恰当)。

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

比如“万”字在45区82位,所以“万”字的区位码是:45 82(注意,GB类汉字编码为双字节编码,因此,45相当于高位字节,82相当于低位字节)。

2.

GB2312字符集中:

1)01~09区(682个):特殊符号、数字、英文字符、制表符等,包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母等在内的682个全角字符;

2)10~15区:空区,留待扩展;

3)16~55区(3755个):常用汉字(也称一级汉字),按拼音排序;

4)56~87区(3008个):非常用汉字(也称二级汉字),按部首/笔画排序;

5)88~94区:空区,留待扩展。

 

二、国标码(交换码)

1.

为了避开ASCII字符中的不可显示字符0000 0000 ~ 0001 1111(十六进制为0 ~ 1F,十进制为0 ~ 31)及空格字符0010 0000(十六进制为20,十进制为32)(至于为什么要避开、又为什么只避开ASCII中0~32的不可显示字符和空格字符,后文有解释),国标码(又称为交换码)规定表示汉字的范围为(0010 0001,0010 0001) ~ (0111 1110,0111 1110),十六进制为(21,21) ~ (7E,7E),十进制为(33,33) ~ (126,126)。

因此,必须将“区码”和“位码”分别加上32(十六进制为20,可写作20H或0x20,后缀H或前缀0x都可表示十六进制),作为国标码。也就是说,国标码相当于将区位码向后偏移了32,以避免与ASCII字符中0~32的不可显示字符和空格字符相冲突。

2.

注意,国标码中是分别将区位码中的“区”和“位”各自加上32(20H)的,因为GB2312是DBCS双字节字符集,因此国标码属于双字节码。

这样我们可以算出“万”字的国标码十进制为:(45+32,82+32) = (77,114),十六进制为:(4D,72),二进制为:(0100 1101,0111 0010)。

(笨笨阿林原创文章,转载请注明出处)

 

三、内码(机内码)

1.

不过国标码还不能直接在计算机上使用,因为这样还是会和早已通用的ASCII码冲突,从而导致乱码。

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

2.

由于ASCII码只用了一个字节中的低7位,所以,这个首位(最高位)上的“1”就可以作为识别汉字编码的标志,计算机在处理到首位是“1”的编码时就把它理解为汉字,在处理到首位是“0”的编码时就把它理解为ASCII字符。

比如:

  77 + 128 = 205(二进制为1100 1101,十六进制为CD)

  114+ 128 = 242(二进制为1111 0010,十六进制为F2)

3.

我们可以来检验一下。打开记事本输入“万”字,编码选择为ANSI(Windows记事本中的ANSI编码在简体中文版操作系统中默认为GB类编码,详见后文解释),保存,如下图所示。

然后用二进制编辑器(比如UltraEdit)打开刚才保存的文件,切换到十六进制模式,会看到:CD F2,这就是“万”字的内码,如下图所示。

4.

小结一下:

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

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

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

(注:十六进制数既可通过添加后缀H来表示,也可通过添加前缀0x来表示)

 

四、为什么要加上20H和80H?

1.

区位码、国标码、内码的转换非常简单,但令人迷惑的是为什么要这么转换?

首先,需要注意到一点,GB2312虽说是汉字编码方案,但其实里面也有针对26个英文字母和一些特殊符号的编码,按理说这些和ASCII重合的字符(33~127)应该无需再重新编码,直接沿用ASCII编码不就行了?

2.

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

而对于ASCII中前32个不可显示也不可打印的控制字符(ASCII码为0~31),以及第33个可显示但不可打印的空格字符(ASCII码为32)等一共33个不可打印字符的编码则直接沿用,不再重新编码。

3.

因为要保留这33个不可打印字符,就不能直接采用区位码作为计算机直接处理的机内码,需要将区位码向后偏移32以避开冲突(为什么是偏移32,而不是偏移33?因为区位码中的区码和位码都是从1开始计数的,不像ASCII码是从0开始计数的)。

十进制数字32的十六进制表示就是20H,这也就是区位码的区码和位码都分别要加上20H才能得到国标码的原因。

(笨笨阿林原创文章,转载请注明出处)

4.

不过,如果直接采用国标码作为计算机直接处理的机内码的话,还是会与ASCII编码产生冲突,导致乱码。

因为国标码虽然相较于区位码避开了ASCII码中0~32的前33个不可打印字符,但并没有避开ASCII码中的英文字母、数字和符号等可打印字符(33~126,共94个字符)以及不可打印的DEL(127)。也就是说,国标码并不是完全兼容ASCII码的。

5.

为了彻底避免与ASCII码的冲突,考虑到ASCII码只使用了一个字节中的低7位,其最高位(即首位)总是为0,于是决定将国标码中每个字节的最高位设为1(国标码的两个字节中的最高位都总是为0,即国标码中的每个字节与ASCII码一样实际上也只用了一个字节中的低7位),这就是GB2312的机内码(即内码),简称GB2312码。

这样一来就彻底区分开了ASCII码和GB2312码。这也是为什么国标码还要加上(80H,80H)才能得到机内码的原因。

6.

看到这里,有人或许又要问了:如果仅仅是为了避免与ASCII码相冲突,为什么最初不直接将区位码的区码和位码的最高位从0改为1(相当于各自直接加上128),这样不就无需经过国标码多此一举的中间转换了吗?而且还无需后移32,也就不用浪费这部分编码空间。

对此本人也很困惑,在网上搜了很久也没找到答案,因此具体原因不得而知。或许是一开始考虑不周?或许是为了未来扩展所需而预留一部分空间?又或许是有其他不得已的原因?有知道的朋友还望能指点迷津。

GB2312区位码、国标码、内码对照表(其中汉字内码B0A1~F7FE,共6763个)

 

五、外码(输入码、输入法编码)

1.

外码也叫输入码、输入法编码,是用来将汉字输入到计算机中的一组键盘符号,是作为汉字输入用的编码。

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

2.

目前常用的汉字外码分为以下几类:

1)数字编码,比如区位码;

2)拼音编码,比如全拼、双拼、自然码等;

3)字形编码,比如五笔、表形码、郑码等。

3.

汉字外码往往会出现重码。

所谓重码,指的是同一个汉字外码对应于多个汉字,反过来说,也就是可能有多个汉字的外码是相同的,相当于重复了,所以称之为“重码”。比如使用拼音作为外码时(即使用拼音输入法输入汉字时),重码现象是相当普遍的。

当出现重码时,往往需要附加选择编号以具体确定所要输入的汉字,这种情况下,可认为外码实际上相当于隐式地包括了选择编号在内。

 

六、字形码(字型码、字模码、输出码)

1.

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

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

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

2.

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

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

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

3.

显然,字形码所表示的字符,相对于抽象字符表ACR里的“抽象”字符,可称之为“具体”字符,因为已经具有了“具体”的外形。

4.

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

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

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

 

七、总结

1.

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

通过键盘输入汉字外码,然后输入法将汉字外码转换为当前操作系统所默认采用的字符编码方案的字符编号(即码点值),再根据字符编号通过代码页查表的方式转换为汉字内码(代码页详见前文的介绍),以实现输入汉字的目的;然后根据所选择的字体,通过汉字内码在字模库(即字库)中找出与字体相对应的字形码,从而将汉字内码转换为汉字字形码,以实现显示输出和打印输出汉字的目的。

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

2.

注意,ASCII码,以及EASCII、ISO 8859系列、GB系列、Big5和Shift JIS等既兼容ASCII码又互相之间不兼容的ANSI编码(“ANSI编码”是对世界上各个国家和地区所制定的既兼容ASCII码又互相之间不兼容的各种字符编码的统称,下一篇文章将详细介绍这个统称的来龙去脉),都属于传统字符编码模型,而不属于现代字符编码模型,很难直接简单套用现代字符编码模型中的概念来表述。

如果一定要套用的话,就GB系列编码而言,勉强来说,区位码相当于现代字符编码模型中编号字符集CCS的字符编号,国标码相当于字符编码方式CEF的码元序列,而机内码则相当于字符编码模式CES的字节序列。

不过,由于GB系列编码虽然是多字节编码,但码元却是单字节码元(码元的概念后文有详细介绍),因此不存在字节序问题,也就不存在字符编码模式CES中的大端序、小端序的概念(字节序以及大端序、小端序的概念后文有详细介绍)。

(笨笨阿林原创文章,转载请注明出处)

 

 

【预告:下一篇将重点剖析非常容易令人困惑的所谓ANSI编码与代码页(Code Page),敬请关注!

 

 

0x80~0x9f 在ISO 8859中是C1控制字符,兼容原因

 

 

 

 

 

 

 

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

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

相关文章

公共链接url出错_SEO优化技巧:关于URL的优化方法

点击标题下「蓝色微信名」可快速关注URL优化需要遵循一些原则, 采用以下方法,网页的用户体验更佳,同时对搜索引擎更友好。01URL越短越好对于搜索引擎来说,只要URL不超过265Byte,收录就没有问题。如果使用几百个字母的U…

【转】刨根究底字符编码之七——ANSI编码与代码页

一、ANSI编码 1. 如前所述,在全世界所有国家和地区的文字符号统一编码的UCS/Unicode编码方案问世之前(UCS、Unicode后文有详细介绍),各个国家、地区为了用计算机记录并显示自己的字符,都在ASCII编码方案的基础上,设计了各自的编…

Angular 下拉搜索框实现

今天有个需求要写一个下拉搜索框&#xff0c;本来是下拉框的&#xff0c;由于内容太多&#xff0c;所以添加一个查找功能。根据博客进行改写的。参考了他的基本框架进行实现。 效果图&#xff1a; 输入框右边的白色箭头图片下载地址 <td>xxxxxxx</td> <td sty…

新手前端练手网站_编程到底难不难学?新手入门选择哪种语言好?

以下内容适合的读者&#xff1a;想要学习编程的小白一.编程到底难不难学&#xff1f;对于这个问题我的回答是不知道&#xff0c;学会了编程的人会说好学&#xff0c;中途就放弃的人会说很难&#xff0c;任何知识想要掌握好都不是一件容易的事情。所以我决定用自己的实际行动来证…

【转】刨根究底字符编码之八——Unicode编码方案概述

Unicode编码方案概述 1. 前面讲过&#xff0c;随着计算机发展到世界各地&#xff0c;于是各个国家和地区各自为政&#xff0c;搞出了很多既兼容ASCII但互相之间又不兼容的各种编码方案(微软统一称之为ANSI编码&#xff0c;具体体现为各种ANSI代码页)。 这样一来&#xff0c;同…

Angular 自定义属性指令-禁止input框输入空格-以及删除复制内容中的空格

创建一个ts文件&#xff0c;并在module.ts中定义 import { Directive, ElementRef, HostListener, Input } from angular/core; import { FormGroup, FormControl, NgControl } from angular/forms; Directive({selector: [input-noSpace]}) export class NoSpace {constructo…

基于androidx的快速开发框架_Vue企业级优雅实战07框架开发03封装基于MockJS的模拟数据...

预览本文的实现效果&#xff1a;# giteegit clone gitgitee.com:cloudyly/dscloudy-admin-single.git# githubgit clone gitgithub.com:cloudyly/dscloudy-admin-single.gitgit checkout 05_MockJS本文主要内容&#xff1a;基于 Mock JS&#xff0c;优雅设计网络请求的模拟数据…

【转】Net Framework,Net Core 和 Net Standard 区别

前几天我在一个群里看到有关这方面的讨论&#xff0c;最后感觉讨论的不是很清晰&#xff0c;有幸的是我们的项目去年就开始迁移NetCore的调研了&#xff0c;我个人多多少少也是有过这方面的研究。下面我将说一下我自己对着三个的认识如果有不足的地方&#xff0c;请大家指出。 …

记录一次SQL优化,增加索引,随便写的当笔记了

写了一个SQL&#xff0c;前端往返时间大约1.7秒&#xff0c;最终优化到一共150毫秒左右&#xff0c;应该还可以更好一些 下面说的有点乱&#xff0c;有空再好好总结一下吧。参考文章里面写的还是比较好的&#xff0c;只不过没有组合查询。 参考链接&#xff1a;https://zhuan…

使用函数求最大公约数 pta_高中数学选修教材2-导数第6课时《函数的单调性与导数》教学设计...

选修2-2第一章1.3.1 函数的单调性与导数一、先复习一下&#xff0c;上节课讲到了利用导数求曲线的切线方程(点我)&#xff0c;咱们这节课接着讲利用导数判断函数的单调性。二、做出图像形象生动&#xff0c;让学生看到当斜率为正(亦是导数为正)的时候函数图像是上升的&#xff…

java程序员_Java程序员工资为什么这么高?

众多行业中&#xff0c;程序员当然属于高薪职业。无论是国内还是国外&#xff0c;IT行业的程序员、工程师&#xff0c;甚至连码农都要比其他行业的从业者的收入高很多&#xff01;尤其是作为IT界的“常青树”Java&#xff0c;原因是什么&#xff1f;01Java行业市场需求存在巨大…

【转】深入浅出OOP(六): 理解C#的Enums

MSDN定义&#xff1a;枚举类型&#xff08;也称为枚举&#xff09;为定义一组可以赋给变量的命名整数常量提供了一种有效的方法。 例如&#xff0c;假设您必须定义一个变量&#xff0c;该变量的值表示一周中的一天。 该变量只能存储七个有意义的值。 若要定义这些值&#xff…

usb接口供电不足_AMD RX 6000 系列显卡配备USB-C 接口,支持外接供电

IT之家 10 月 29 日消息 根据 AMD 的官方信息&#xff0c;新发布的 RX 6000 系列显卡进一步增强了显示能力&#xff0c;配备了 HDMI 2.1 接口、DP 1.4 接口和 USB-C 接口。AMD 表示&#xff0c;AMD Radeon 6000 系列显卡全部搭载 HDMI 2.1 VRR 接口&#xff0c;超大带宽支持最高…

【转】VS2005键盘布局_快捷键大全(总结了一些记忆的口诀)

VS快捷键对提高生产力有莫大帮助&#xff0c;本文将所有快捷键进行了重新整理归类&#xff0c;便于记忆。有缺失&#xff0c;不足之处&#xff0c;还请大家指出&#xff0c;谢谢 1、窗口快捷键 &#xff08;W代表Windows也就是窗口的意思&#xff09; CtrlW,A: 命令窗口&#…

mac securecrt程序无响应_如何重置mac上的系统管理控制器smc教程

虽然mac是一款十分高端的个人笔记本电脑&#xff0c;但是mac也会有出现故障的时候&#xff0c;比如风扇高速转动、键盘背光灯行为有些异常异常等等&#xff0c;那极有可能是你的系统管理控制器smc出现了问题&#xff0c;所以今天小编就来科普大家如何重置系统管理控制器smc。如…

bootstraptable treeGrid 懒加载_Java类加载机制及自定义加载器

一&#xff1a;ClassLoader类加载器&#xff0c;主要的作用是将class文件加载到jvm虚拟机中。jvm启动的时候&#xff0c;并不是一次性加载所有的类&#xff0c;而是根据需要动态去加载类&#xff0c;主要分为隐式加载和显示加载。隐式加载&#xff1a;程序代码中不通过调用Clas…

Idea打可执行jar包

前些日子试了下idea打包&#xff0c;有些细节没太注意所以经常打包失败&#xff0c;要不然就是显示没有主清单属性&#xff0c;所以一直用eclipse打包&#xff0c;今天又重新捣鼓了一下&#xff0c;写下过程&#xff1a; 1. 先添加需要打jar包的主入口 第三步一定不要放在main…

安卓系统挂载NTFS格式硬盘_Mac 读写 NTFS硬盘管理开源工具NTFSTool

NTFSTool是Mac OS 下一款开源的 NTFS 磁盘格式读写工具&#xff0c;基于Electron和VUE编写。遵守MIT开源协议。支持 NTFS 磁盘读写、挂载&#xff0c;退出、管理等功能。系统检测到插入移动硬盘后&#xff0c;会自动弹出 NTFSTool 界面&#xff0c;并自动挂载硬盘。安装NTFSToo…

【转】刨根究底字符编码之九——字符编码方案的演变与字节序

字符编码方案的演变与字节序 一、字符编码方案的演变 1. 根据前面的介绍&#xff0c;对于字符编码方案的演变&#xff0c;我们大致上可简单地划分为三个阶段&#xff1a; ① ASCII编码方案阶段 → ② ANSI编码方案阶段 → ③ Unicode/UCS编码方案阶段。 在第一个阶段的ASCII…

python人工智能_人工智能人才缺口千万!学Python抓住风口机会

前不久教育界的一个消息&#xff0c;引发了广泛的关注。今年9月&#xff0c;浙江三到九年级信息技术课将替换新教材&#xff0c;八年级将新增Python课程内容。新高一信息技术编程语言由VB替换为Python&#xff0c;大数据、人工智能、程序设计与算法按照教材规划五六年级开始接触…