本文简单回顾了汉字编码的历史沿革,试图寻找不同领域的汉字编码规则下隐藏的通用逻辑。
前言
小时候玩美版宝可梦叶绿(即初代绿版在第三世代的复刻),在七之岛上的石板可以看到一串神秘符号,特点是每个符号都由3x2总共6个点组成,并且每个点有浅色深色两种状态。后来在贴吧看到大佬解答,才知道原来这就是所谓的布莱尔盲文,这些符号与英文字母一一对应。不过,也不是说玩家必须要知道布莱尔盲文才能破解石板上的信息,因为游戏里已经做出了提示:七之岛的某个洞穴房间里按照顺序排列好了所有符号的盲文表示,英文字母加上逗号句号共计28个。小时候的我甚至还抄了份笔记利用上下学的时间把盲文字母表背了下来。多年以后的现在,常用字母和字母序靠前的我还能记得,不常用的就全忘了。毕竟光说不练的死知识忘得很快(对我来说还是不要有练习盲文的机会比较好)。
初中的我其实并没有聪慧到能够自主地理解那个提示有盲文信息的洞窟究竟是什么意思(也可能是在每周只能玩两个小时游戏机的漫长时间跨度里把这个没什么游戏性的房间忘了个一干二净)。在我开始背诵布莱尔盲文字母表之前,我在互联网上先搜索到了某一本书的某一章节[1],这才对盲文有了比较系统的了解。
此书名为《编码:隐匿在计算机软硬件背后的语言》,从摩尔斯电码、布莱尔盲文等前计算机时代的编码案例出发,带领读者一步一步走进计算机里的编码世界。这本书由大佬写就,从最简单的案例出发,自然而然地引出一个非计算机专业的人很难搞清楚的一件事情:计算机内部是如何用01二进制编码表示一切的。
现在看来,真是一本优秀的深入浅出的科普读物,但当时的我还没有开始学习编程,对此书兴趣也不大。只是恰逢此书中文翻译版刚刚发售,有零零散散的免费试读章节在互联网上流动,而这个免费试读章节正好是讲布莱尔盲文的第三章,我才凑巧与该书相遇。学完布莱尔盲文的基本规则之后我就再没了解过此书,买更是不可能买的,没钱。虽说没有完整地看过,但是仅仅是有关布莱尔盲文的第三章,也使我受到非常多的启发。
本来我以为,盲文有关的知识迟早被我淡忘。
直到,前段时间刷到了这个知乎问题——
上海外滩附近一处木栏杆上的这个图案是什么意思?https://www.zhihu.com/question/644205270/answer/3396006285仔细观察后发现,图中盲文用每两个布莱尔符号(英文盲文符号,即图中3x2的点阵)表示一个汉字的读音,所有的声母字母和英文盲文一致。所以我推测盲文遵循一种双拼规则,即一个符号表示声母,另一个符号表示韵母的汉语拼音方案。查阅资料发现确实如此。
盲文、双拼,本来我心目中毫不相干的两个概念此时交会在一起。这也解答了我多年来的一个小小的疑惑:使用布莱尔盲文至多64个符号,如何表示成千上万个汉字?
用一句话直接公布答案是毫无益处的,既不能说清楚盲文的规则,又不能让人充分地明白其背后的原理。因此,本文将从计算机的视角出发,介绍对比历史上的各种汉字编码方案,旨在使读者最终能够深入了解国家通用盲文方案与其背后的编码原理。
中文电码
中文电码,或称中文商用电码,原本是用于电报之中传送中文信息的方法,也是将汉字编码成电子信号序列的初次尝试。
作为19世纪最先进的通信手段之一,电报被列强想方设法地带入中国。 1871年,大北公司铺设海底电缆,搭建了海参崴-长崎-上海电报线路。虽然清政府极力阻止,但是架不住老百姓要用,而且她自己没多久就真香了。随着中国国内电报线不断开设,电报最终成为了清政府总理衙门沟通驻外使臣的重要渠道[2,3]。直到20世纪末,由于传真、电话等新型通信手段的出现,电报逐渐消亡了。现如今,除了告白和怀旧,应该没有人使用中文电码了。
1871年,法国驻华人员Septime Auguste Viguier在中国文人的帮助下,参照《康熙字典》的部首排列方法,挑选出6800多个常用汉字编成第一部汉字电码本《电报新书》[3]。
西文电报是用摩尔斯电码传输的,最长只有6个点划,因此摩尔斯电码最多可以表示26 = 64种符号。那么,成千上万的汉字该怎么使用点划表示呢?《电报新书》给出的解决方案是,给每一个汉字分配一个四位数字(十进制数字,即0-9)的唯一编码,反过来说,每个四位数字也仅仅对应一个汉字(或者没有对应汉字)。除去电报符号、数字和月份等特殊符号,这种方案最多可以给将近10000个汉字进行编码。后续诞生的电报规范都遵循这一规则,使用四个数字表示一个汉字。
举个例子。
假如韩梅梅要向李雷表白,但是过于直白地表达心意会让她害羞到爆炸。于是韩梅梅选择中文电码作为“加密”,这不仅可以防止其他人偷窥两人之间的通信内容,而且也避免了对方当场看懂当场答复。毕竟表白之后焦躁不安的等待也是一种重要的体验嘛。
为了把爱意传达给喜欢的人,首先需要把汉字序列转换为对应的数字序列。根据《标准电码本(修订本)》1983年9月第3版,韩梅梅设计了简短的告白: 我 爱 你 之后,把写有205319470132的小纸条放在李雷的桌子上,等待对方发现。李雷看到纸条上的神秘数字,不知道是什么意思。来回翻看小纸片,终于在角落里发现了一行小字“中文电码”,于是查阅标准电码本把每四个数字翻译成汉字。虽然意思懂了,但他还是有个小小的疑问。
“我、爱、你…………是谁呀?”
诶呀,忘记署名了。
-·-·-
在上例中,从信息的发送方到接收方,信息的编码形式经历了“汉字-数字-汉字”的一系列转换,如图1所示。如果是通过电报传播,数字还需要再被翻译成摩尔斯电码,接收方需要先从摩尔斯电码翻译出数字,然后再翻译出汉字。不难发现,中文电报的成本高昂。电报员不仅需要熟练地从摩尔斯电码提取出数字,还需要背诵几千个常用字的电码表。
计算机里的中文编码
信息时代,随着计算机的兴起与发展,各国纷纷开始制定本国文字的显示方案。其中最为重要的概念就是字符编码和字符集。
字符编码
字符编码是字符的集合与其二进制编码的集合之间的映射,例如摩尔斯电码就是拉丁字母的一种编码方式,同时也是拉丁字母的一个字符集。同时,字符编码是双射,即每一个字符有且仅有一个二进制编码,每一个二进制编码也有且仅有一个与之对应的字符。例如,在ASCII编码里,小写字母a的编码是0x61,反过来也可以说,0x61表示小写字母a,而不能表示其他任何符号。
众所周知,英文只有26个字母,仅有7比特宽度的ASCII编码不仅包含大小写字母和数字,还有余裕添加众多控制字符 (control characters)。 ASCII码诞生于通信需求,为确保信息传递无误,通常要再添一个最高位作为校验位,所以有时ASCII码的宽度是8比特。但是对于计算机存储来说,校验位就没有那么必要了,而且不能利用的1字节对紧俏的内存来说非常浪费(毕竟还是软盘的年代)。
为了兼顾通信需求和计算机储存需求,非英语国家通常遵循ISO/IEC 2022标准为本国语言制定编码标准,简体中文的第一个国家标准就是大名鼎鼎的GB/T 2312了。
字符集
字符集是指编码规则所规定的,具有二进制编码的字符。在计算机基础设备与软件发展趋于成熟的时今天,各种编码规则的字符集越来越大,以至于从业者有时不得不只实现其中的一部分,也就是“子集”。例如,MYSQL等数据库可以制定字符集为utf8mb3
或是utf8mb4
,他们都是UTF-8编码,但是包含的字符集范围不同。后面的章节将会详细地介绍。
GB2312 和 GBK
GB/T 2312(后简称GB2312)是中华人民共和国国家标准简体中文字符集,全称《信息交换用汉字编码字符集·基本集》,由中国国家标准总局于1980年发布,1981年5月1日实施。 GB2312共收录6763个汉字,其中一级汉字3755个,二级汉字3008个;同时收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个字符。
在GB2312的编码规则下,每个汉字用两个字节表示。而这两个字节并不能从0x00-0xFF
里任取,他们的范围是0x21-0x7E
,共计94个8位二进制数。这是为了与ISO/IEC 2022标准兼容,此时的编码方案被称为国标码。如果还需要跟ASCII兼容的话,就要把最高位置1,此时每个字节的取值范围就变成了0xA1-0xFE
。这种GB2312编码的变种被称为机内码。根据表1不难看出这两个范围的关系。
表1: 一些16进制数字的2进制表示0x21 | 0010 | 0001 |
0xA1 | 1010 | 0001 |
0x7E | 0111 | 1110 |
0xFE | 1111 | 1110 |
GB2312中字符编码的第一个字节叫区,第二个字节称为位。每区含有94个汉字/符号,共计94个区。例如“爱”在16区14位,所以“爱”的区位码是1614(16是区码,14是位码)。
那么,具体而言,“爱”的GB2312编码是多少呢?前面提到,GB2312如果要与ASCII兼容,要从0xA0
开始算起。所以,“爱”的区码是0xA0+16
,位码是0xA0+14
。计算得到“爱”的GB2312编码是0xB0AE
。
1
| printf "\xB0\xAE" | iconv -f GB2312 -t UTF-8
|
在Linux环境下可以用这个指令验证一下,后边的iconv是因为terminal一般默认UTF-8,所以要转换一下才能显示。毕竟GB2312已经是非常非常老的标准了,现在被最广泛使用的是扩展了GB2312的GBK编码。
汉字内码扩展规范,简称GBK(“国标扩”的首字母),1995年12月首次公布。GBK共收录21886个汉字和图形符号,其中汉字(包括部首和构件)21003个,图形符号883个。GBK编码曾是国内最常见的编码,在很长一段时间里,国内发行的操作系统、软件、网页等都使用GBK编码来存储中文字符串。例如Windows 95操作系统默认的中文编码就是GBK编码。GBK完全兼容GB2312,并在此基础上扩大了区位码的范围。不准确地讲,相比于原本的内码方案,GBK的区码范围扩大到了0x81-0xFE
,位码范围扩大到了0x40-0xFE
。
UTF-8
UTF-8 (8-bit Unicode Transformation Format)是Unicode字符集(巴别塔级的什么符号都有的超大字符集)的一种可变长的编码形式。 UTF-8是可变长的,在此编码规则下一个字符的二进制编码可以是1、2、3甚至4个字节宽。 UTF-8只是Unicode的一种实现,除此之外还有其他的编码方案,且不一定非要是变长的,例如UTF-16就是两字节宽的定长的映射方案。
在Unicode众多的编码方案里,UTF-8是最受大力推行的一种。因为UTF-8编码变长的特点,可以为使用拉丁字母的语言节省不少存储空间。 表2展示出UTF-8编码的特点,不同范围的Unicode在经过UTF-8编码之后所占字节数也不同。与此同时,在需要解析UTF-8字节流的时候,可以通过字节的高位部分判断哪几个字节需要放到一起而表示一个符号。
表2: UTF-8编码原理0000 - 007F | 0xxxxxxx |
0080 - 07FF | 110xxxxx 10xxxxxx |
0800 - FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
例如,“爱”的Unicode编码是0x7231
,位于0x0800-0xFFFF
之间,所以需要三个字节编码,具体的编码方式如图2所示。编码时首先把0x7231
展开成二进制,然后从低到高依次填到表2的模板里,也就是若干个“x”所在位置。 UTF-8编码的中文都是3字节的。这就是为什么QQ昵称剩余可输入字符总是随着汉字的输入以3的倍数减少。
不难发现,表2里右边每个字节的前几个比特都不太相同。这是为了方便解析UTF-8字节流。对于定长编码的字节流,比如一段GBK编码的字节流,只需要每两个字节一组地进行解析。但是UTF-8是变长编码,字节流状态机需要辨别当前字节,因此每个字符编码的开头需要包含一定的信息。例如以1110
开头的字节是三字节字符的第1个字节,以0
开头的是单字节字符。我们可以发现一个规律:除单字节的编码需要兼容ASCII之外,字符编码开头有几个1就是几字节宽。为了隔开数据段,这些1后面还需要再接一个0。
一个解析UTF-8字节流的C代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| uint n; WIDE_CHAR wideChar; BYTE *byte;
while (byte = getBytes(1)) { if (byte & 0xE0) { n = 3; } else if (byte & 0xC0) { n = 2; } else if (byte & 0x80) { } else { n = 1; }
assemble_wide_char(&wideChar, n, byte, getBytes(n - 1)); }
|
上面是一个解析UTF-8字节流的C代码示例。每次while循环开始时取一个字节,如果为空则终止循环。取字节之后根据该字节最高位的信息计算还需要取几个字节,在本次循环结束前组装wideChar
,然后进一步处理。处理结束后进入下一次循环。
其实UTF-8编码还考虑了大小端(endian)问题:UTF-8字节流开头两个字节一定是0xFEFF
或者0xFFFE
,用以指示当前字节流的大小端。但是大小端不是本文讨论的重点因此按下不表。
中文拼音输入法
拼音输入法是我国主流的输入法。只要是接受了几年义务教育的中国人,学习全拼输入法的速度几乎等同于熟悉键盘的速度。
早在小学时,信息课老师就要求我们把电脑键盘布局背下来,甚至还要默写。但是愚钝的我一点也背不下来,抄了同桌的QWERT和ASDF之后就直接交卷了。信息课老师还仔细地教我们打字的正确姿势,比如两手食指放到FJ两个按键上面定位,哪些字母用那根手指去按之类的。
他可能真的想教会我们。
但是之后的十年里我长期处于二指禅打字的状态,直到上大学的时候有了大量打字的需求才逐渐改善。
当时我们还有上机实践的课,一般用智能ABC(一种Windows XP自带的拼音输入法)练习全拼打字。打字测速使用的文章叫做《冰灯》,作为一个哈尔滨人看了感觉非常奇妙。
打字测速https://dazi.kukuw.com/智能ABC除了默认的全拼模式,还能双拼。在菜单里切换全角半角符号的按钮旁边,就是切换全拼双拼的按钮。小学的我姑且搞明白了全角半角是什么意思,但对于双拼的印象只有“如果按了那个按钮就不能正常打字了”。直到去年,为了提高一点打字速度,同时也避免别人拿我的手机电脑假冒我(并没有人这样做),我学习了双拼。自此,我才彻底弄明白双拼是什么。
首先我们先来回顾一下全拼输入法。
全拼输入法
使用全拼输入法输入“广电”两个字,只需要先输入汉语拼音guangdian,然后从“广电”、“光电”、“光点”等候选项里选择想要的汉字短语(对于此种情况来说就是第一个),按键盘上的数字1,屏幕上的一串英语字母就变成了汉字。可以看出,使用拼音输入法打字只需要两个步骤:(一)输入拼音,(二)选择短语。如果想要的短语正好处在第一个,除了按数字1之外还可以用空格表示选定。
全拼输入法简单易学,但是也有两个缺陷。首先是同音字词过多导致的重码率高。重码指汉字不一样但是拼音编码一样的字词,因为重码的存在,所以输入拼音之后不能直接把拼音变成汉字,还需要一个选择字词的阶段。随着近年来输入法联想功能变得越来越强大,重码问题得到了一定的缓解。但是输入生僻字的时候,打字速度还是会被极大地拖慢。而且,并不是所有的输入法都有强大的联想功能。 Ubuntu默认的拼音输入法就没有,当年成为我使用一台Ubuntu系统的电脑作为主力机的障碍之一。
第二个问题是击键频率问题。我们知道,汉语拼音里声母几乎都只有一个字母,而韵母的长度却是不定的。这就导致有的字的拼音很短,有的字的拼音却很长。这导致打字效率难以提高。打字员心里思考“阿嚏”和“广场”两个字的时间是一样的,但是打字速度却差了许多倍,就是因为后者的拼音太长。
双拼输入法
双拼输入法可以解决全拼输入法的击键频率问题。
所谓双拼,就是指两个字符的拼写规则:用一个字母表示声母,另一个字母表示韵母。这样就可以表示每一种拼音了。双拼输入法本质上还是拼音输入法,因此无法解决重码问题。只不过,双拼规则下拼音的长度固定为两个字母,击键频率比全拼少了不少,打字速度也应有所提升。例如,小鹤双拼方案下“小鸟”的编码为xn'nn。其中字母n表示韵母iao。 图3是小鹤双拼方案的键位图。在该方案中,每个英文字母既可以作为声母也可以作为韵母,甚至可以同时表示多个韵母。实际上,所有的双拼方案都是如此,不然如何表示众多的声母韵母呢?
要判断用户输入的字母是声母还是韵母,我们可以使用一个简单的有限状态机,如图4所示。当输入第1个字符时,它一定是声母。输入第2个字符时,如果它可以与前一个字母组成拼音,那么它就被看作是韵母;如果不能,那只能将它看作是声母了。例如,d'uang并不能代表一个现代汉语里的汉字,那么这个拼音就是没有意义的(即使口语里可能存在这种拼音搭配)。如果采用小鹤双拼方案,其编码d'l会被理解成两个字的辅音,而非duang。
对于本来就只有一个韵母的拼音,例如“啊”的拼音a,有的双拼规则使用“零声母”规则,例如规定o为零声母,那么“啊”的拼音就写作oa;有的双拼规定重复规则,此时“啊”的拼音就写作aa。对于只有复元音韵母的拼音,其双拼规则与全拼时一致。例如“奥”的拼音就是ao,全拼和双拼时都是如此。虽然有的复元音需要用三个字母才能表示,比如iao,但是这种复元音不能单独表示一个字。
此外,少量的汉语拼音声母原本是用两个英语字母表示的,现在必须要用一个字母表示了。好在这样的声母不多,只有卷舌音系列的zh、ch和sh。拼音里的六个元音字母a、o、e、i、u、和v(ü),分配其中的三个给卷舌音当声母,还能有余裕再选出一个当零声母。
顺便一提,我在练习双拼输入法的初期,总是想把“叶”字打成ie;由于感觉“圆”和“团”的韵母不太一样所以找不到uan在哪里。
布莱尔盲文
为了更好地理解中文盲文,我们首先从英文盲文开始。
英文盲文采用的方案叫布莱尔盲文(braille),其名称是为了纪念其法国发明者布莱尔。布莱尔盲文的最小组成单元叫做“方”(cell),是一个3x2的点阵,共有6个点。其中每个点可以有两种状态:凸起/平坦。盲人阅读时,通过点阵的触感辨认出每个方相应的英文字母。为了读者方便,本文使用实心/空心的圆来表示点的凸起/平坦状态。并且对每方的点位编号,第一列从上到下分别为1、2、3,第二列从上到下为4、5、6。例如⠁的点位是(1),⠍的点位就是(134)。
布莱尔盲文的每个字符有6个点,因此最多有26 = 64种字符。而英文只有26个字母,还不到这个数字的一半。为了尽可能地缩减盲文句子的体积,一些常见的字母组合和单词就被添加进来。此时,“加了料”的盲文叫做二阶布莱尔盲文(2nd grade braille),而没有“加料”的盲文叫做一阶布莱尔盲文(1st grade braille)。英文盲文字母表参见维基百科。
例如,you and me的一阶布莱尔盲文为
如果改用二阶布莱尔盲文,则可以写成
其中⠽不仅可以表示字母y,单独使用时也可表示单词you;⠯表示单词and,该符号在一阶布莱尔里没有对应。
国家通用盲文方案
国家通用盲文方案是一套带声调的盲文双拼方案,沿用了布莱尔盲文的符号。也就是说,每个汉字最多用三个方来表示:第一个方是声母,然后是韵母,最后是音调。为了提高盲文的阅读速度,与二阶布莱尔盲文类似,有时仅用一个或者两个方来表示一个汉字,具体的省写与简写规则将在后面详细介绍。
注 本文旨在介绍国家通用盲文方案(一下简称方案)的编码思路,由于本网站中盲文排版不是很方便,因此不把对照表格全部复制于此,具体的盲文符号对照表参见教育部官方文件。
声母
绝大多数的声母与英文盲文相同,例如⠃表示b(波),⠍表示m(摸)。但是,方案的声母对照表有两个细节值得注意。
表3: 一些声母的盲文符号表⠌ | (16) | zh |
⠟ | (12345) | ch |
⠱ | (156) | sh |
⠎ | (234) | s |
⠛ | (1245) | g、j |
⠅ | (13) | k、q |
⠓ | (125) | h、x |
其中之一在前面双拼输入法的时候我们也面对过:为了使用一个方来表示卷舌音声母,需要给他们新的编码(因为英文盲文里没有)。方案给出的答案是,分别将zh、ch、sh编码为⠌、⠟和⠱。其中sh的编码正好是s的编码的水平翻转,体现了一丢丢方案总则里的易学原则。
第二个细节是,有三个盲文符号可以分别表示两种声母:g / j、k / q和h / x。例如,⠛可以表示g,也可以表示j。根据方案所述,当这些声母后接i、ü开头的韵母时读作j、q、x;与其他韵母相拼时读作g、k、h。实际上,这三组声母就是所谓的尖团音。
P.S. 看来盲文里没法表示hia'hia'hia的笑声。
韵母
方案中共使用34个符号表示总共35个韵母。首先考察所有的单声母:a、o、e、i、u、ü。
表4: 一些韵母的盲文符号表⠔ | (35) | a |
⠢ | (26) | o、e |
⠊ | (24) | i |
⠥ | (136) | u |
⠬ | (346) | ü |
⠗ | (1235) | er |
⠕ | (135) | uo |
⠑ | (15) | ie |
在英文盲文里,字母a的符号的地位相当于英语四级词典里的abandon,只有右上角一个凸点,最好记。但是,作为韵母的a却不得不把这一珍贵的符号让出来给声调里的阴平(一声),而获得一个新的符号⠔。韵母o和e的符号为⠔,与a的⠢是水平翻转的关系。韵母o和e共用一个符号应该是因为两者所能搭配的声母完全不重合,更本质的音韵学原因我也不太清楚。注意到,该符号既不是英语字母o的符号(135),也不是英语字母e的符号(15)。这是因为这两个符号分别被分配给了韵母uo和ie。韵母i和u的盲文与相应的英语字母相同,韵母ü的盲文与英语字母v的符号相同,符合国人的拼音输入习惯。
顺便一提,韵母er(同时也可表示儿化音)的盲文与声母r相同,都是⠗。该符号形状上与英文字母r非常相近,是我最先掌握的布莱尔盲文之一。
音调
前文提到,字母a的英文盲文(1)被汉语盲文声调阴平(一声)征用,这是因为这个字符太特殊、太重要了。如果将所有的音调放到一起,可以发现简单又好记。
标点符号
标点符号的盲文表示比较复杂,大量使用了转义字符(Escape character)。本章着重介绍表5所示的一些标点符号。所谓转义字符,就是指该字符后的字符不再表示原有的含义,而与前面的转义字符一起表示新的含义。例如,符号(5)单独出现时是逗号;与汉字相连时是着重号;与本来表示去声的符号相连构成一个整体时(5,23)表示句号;与本来表示连接号(-)的符号相连时的(5,36)表示书名号。
成对使用的符号,如括号、书名号,其盲文也是水平翻转对称的,与英文盲文的惯例一致。省略号的盲文(5,5,5)非常生动,就是三个有些间隔的凸点。由于双引号比单引号常用,所以双引号用一个符号表示,而单引号才需要转义字符,转义方式是把符号重复一遍。
表5: 一些标点符号的盲文对照表⠐ | (5) | 逗号 | , |
⠐ | (5) | 着重号 | · |
⠐⠆ | (5,23) | 句号 | 。 |
⠘ ⠘ | (45)(45) | 双引号 | “” |
⠘⠘ ⠘⠘ | (45,45)(45,45) | 单引号 | ‘’ |
⠤ | (36) | 连接号 | - |
⠐⠤ ⠤⠂ | (5,36)(36,2) | 双书名号 | 《》 |
⠐⠐⠐ | (5,5,5) | 省略号 | … |
拼写规则、省写与简写
前面简单介绍过方案规定的拼写规则,通常情况下每个字由三个符号表示:声母、韵母和音调。例如“中”和“国”的盲文分别为⠌⠲⠁和⠛⠕⠂。如果该字没有声母,就只需要两个字符了,如“爱(ai)”的盲文为⠪⠆,“叶(ye=ie)”的盲文为⠑⠆。整体认读音节的zhi、chi、shi、ri、zi、ci、si,可以省略声母,例如“智”的盲文为“⠌⠆”。
到这为止的盲文规则,我对照英文盲文将其称为“一阶国标汉语盲文”,即没有任何省写和简写。接下来介绍省写和简写规则。
为了提高阅读效率,省略大部分的声调是非常有必要的。方案规定,声母为f的音节省写阴平符号;声母为p、m、t、n、h、q、ch、r、c的音节省写阳平符号,音节tóu除外;声母为b、d、l、g、k、j、x、zh、sh、z、s的音节省写去声符号,音节lè、zì除外。根据上述规则,“和平饭店”的盲文为“和(⠓⠢)平(⠏⠡)饭(⠋⠧⠆)店(⠙⠩)”,其中只有“饭”的上声不能省略。
除此之外还有许多音节可以省写,在此不做过多介绍。
与英文的二阶布莱尔类似地,方案也对最常用的“的”、“么”和容易混淆的人称代词“你”、“他”、“她”、“它”给出了一套省写方案,如表6所示。
表6: 盲文省写对照表的 | ⠙⠢ | ⠙ |
么 | ⠍⠢ | ⠍ |
你 | ⠝⠊ | ⠝ |
他 | ⠞⠔ | ⠞ |
她 | ⠞⠔⠁ | ⠞⠁ |
它 | ⠈⠞⠔ | ⠈⠞ |
当“的、么、你、他、它”后接韵母自成的音节时,不能简写。例如“怎么样”的省写⠵⠴⠄⠍⠢⠭,其中“么(⠍⠢)”不简写。
结论
本文分别介绍了电报所用的中文电码、计算机所用的GBK与UTF-8编码,以及国家通用盲文的编码方案。可以看出,汉字编码方案与其设计目的的关系密不可分。
中文电码使用四位10进制数字表示汉字,是摩尔斯电码与人类计数习惯之间的妥协。 GBK/UTF-8编码使用两字节2进制(也可以说是16进制)数表示汉字,是从计算机存储和处理的角度设计的。而国家通用盲文方案里,被编码的对象基本不是汉字,而是音节。这是因为表意的盲文十分难记,既然人类之间交流时没有字幕(吃菌子的时候除外),不如把盲文设计成表音符号从而降低学习门槛。
中文电码和GBK/UTF-8编码都是双射,即字符集与码表之间都是一一对应的。因为电报和计算机的使用场景对准确性的要求严苛,编码解码流程中不容出现错误。
盲文是一种基于汉语拼音的双拼方案,与双拼输入法相比,拼读规则上有细节的差异。通常,在义务教育里,整体认读音节除了zhi、chi、shi、ri、zi、ci、si外,还包括yi、wu、yu、ye、yue、yuan、yin、yun、ying。在双拼输入法中,所有这些整体认读音节都是声母+韵母的双拼编码,而在盲文的省写规则里,前者只需用声母来表示,后者则都算作单韵母音节,例如zhi=zh,yuan=uan。在笔者看来,盲文的拼写规则或许更贴近现代汉语真正的韵母规律,但是双拼输入法的拼写方案更适合接受了义务教育的人上手。如果将盲文看作是汉字的编码,那么由于现代汉语中大量存在的同音字词,与拼音输入法一样,盲文有严重的重码问题。至于重码问题会不会给盲人的阅读带来阻碍,就不得而知了。
Fin.
参考文献
[1]
[美] Charles Petzold, 左飞, and 薛佟佟译, “编码:隐匿在计算机硬件背后的语言,” 北京: 电子工业出版社, 2012, pp. 15–21.
[2]
人民教育出版社, 课程教材研究所编著, and 历史课程教材研究开发中心, “普通高中课程标准实验教科书 历史2 必修,” 北京: 人民教育出版社, 2007, pp. 68–71.
[3]
薛轶群, “万里关山一线通——近代中国国际通信网的构建与运用(1870-1937),” 北京: 社会科学文献出版社, 2022, pp. 50–81.