问题

计算机内部是如何处理汉字的输入输出和存储过程的?

回答
说起电脑里汉字的输入输出和存储,这事儿说起来可就绕了,毕竟咱们这方块字跟电脑这二进制世界八竿子打不着。不过,这事儿在咱电脑科学里可是个了不起的工程,从早些年笨重的打字机,到如今花样百出的输入法,再到我们眼睛里看到的屏幕上的字,这里头藏着不少门道。

一、 汉字是怎么跑到电脑里的?—— 输入篇

这第一步,就是得让电脑认识我们敲下去的每一个字母、每一个笔画。这可不是简单地“把字敲进去”那么回事儿。

编码的基石:数字代号

你想想,电脑里所有东西,无论是声音、图像还是文字,最终都得变成一串串0和1。汉字也一样。但汉字数量庞大,结构复杂,不像英文字母那么规律。所以,最早的时候,人们就想了个办法:给每个汉字一个独一无二的“数字身份证”。这就是编码。

早期,人们尝试过各种编码方式。比如,区位码就是比较早的一种。它把汉字按照一定的顺序(比如部首、笔画)排好,然后分成一个个区域(区)和位置(位),形成一个四位数的编码。比如,“你”字可能就对应一个区位码。这个编码虽然简单,但输入起来很麻烦,得记住好几个数字。

后来,为了方便输入,有了像拼音输入法。我们输入的拼音,电脑会根据你输入的字母顺序,去匹配数据库里所有以这个拼音开头的汉字。例如,你输入“ni”,电脑会显示一长串带“ni”的字,然后你再按数字选择。这背后,是输入法软件在做大量的匹配工作。

还有更厉害的,比如五笔输入法。它讲究“形”,把汉字拆分成不同的笔画和偏旁部首,然后给这些基本部件分配了字母键。你熟悉了拆字规则,就能快速地把汉字“拆解”成字母,再输入电脑。这种输入法对记忆要求高,但熟练了之后,速度极快,而且重码率低。

输入法的本质就是一种“翻译”:把我们熟悉的语音(拼音)或者字形(五笔)转换成电脑能理解的数字编码。

输入法的“大脑”:键盘与软件的配合

当我们用键盘敲击字母时,键盘会将这些物理动作转换成电信号,然后由操作系统接收。操作系统里的输入法软件,就像一个翻译官,它会实时捕捉你输入的每一个按键,并根据其预设的规则(拼音、五笔、笔画等)进行分析。

拼音输入法会根据你输入的字母,查找其内部庞大的“字库”和“词库”,找出可能的匹配汉字或词组。通常还会结合“词频”和“用户习惯”来优化推荐,让你输入常用词时更加顺畅。
五笔输入法则更像是按照预设的“拆字规则”来解析你的输入,将输入的字母组合与汉字的字形编码进行匹配。

一旦你确定了要输入的汉字(比如通过按空格键选择),输入法软件就会将这个汉字对应的内部编码发送给操作系统。

二、 汉字在电脑里“安身立命”:存储篇

电脑可不知道什么“仓颉造字”,它只认0和1。所以,我们输入的汉字,最终都得变成一串串数字,然后存起来。

编码的另一种面孔:内码与外码

刚才我们说的区位码、拼音编码、五笔编码,这些更多的是“输入”时用的,我们称之为外码。但这些编码在电脑内部直接存储和处理起来,其实并不理想。

为了更有效地在电脑内部传输和存储,就引入了内码。内码和外码不一样,它是电脑内部用来表示汉字的一种编码方式。就像我们出门在外说方言,回家了说普通话一样,内码是汉字在电脑系统里的“官方语言”。

目前国际上最通用的汉字内码是Unicode。它不像以前的编码那样只针对中文,而是为世界上几乎所有的文字系统都分配了唯一的数字编码。在Unicode中,汉字也被赋予了独一无二的码点。

UTF8 是Unicode的一种编码格式。它有一个很巧妙的设计:对于英文字母和数字,UTF8用一个字节表示(跟ASCII编码一样),对于汉字等字符,则用多个字节表示。这样一来,英文文档占用的空间和以前一样小,而汉字文档也不会因为使用了多个字节而显得过于庞大。这就是为什么现在我们看到的网页、文件,大多数都是用UTF8编码的。

GBK 和 GB2312 也是在中国曾经非常流行的汉字编码标准,它们是“内码”的一种。GB2312包含了一万多个汉字和一些符号,而GBK则更加丰富,收录了更多的汉字。但随着国际化的发展,Unicode(尤其是UTF8)已经成为主流。

总结一下就是: 我们输入时,输入法将我们的行为(拼音、五笔)转换成外码,然后通过某种机制(比如输入法软件的映射表)将其转换成内码。这个内码就是汉字在电脑内部的真正身份,可以被存储在硬盘、内存中。

存储:文件里的二进制流

当我们保存一个包含汉字的文件时,文件里存储的其实就是这些汉字对应的内码(通常是UTF8编码)。这些内码是一串串的二进制数字。比如,“你”字在UTF8编码下可能是三个字节的组合。当文件被保存到硬盘上时,这些二进制数据就被物理地存储在硬盘的磁性物质上(或者固态硬盘的闪存颗粒上)。

在存储的过程中,并没有直接存储我们看到的字形,而是存储它的“身份信息”——编码。

三、 汉字是如何“跃然纸上”的?—— 输出篇

我们把信息保存在电脑里了,那怎么才能看到呢?这就需要将存储在电脑里的数字编码,“翻译”成我们能理解的字形。

编码到字形的“桥梁”:字库(字体文件)

电脑里存储的只是汉字的编码,而不是字形本身。那么,电脑是怎么知道“你”字长什么样子的呢?这就需要一个叫做字库的东西,也称为字体文件。

一个字体文件(比如我们常说的宋体、微软雅黑、黑体等)里,包含了成千上万个汉字的字形信息。这些字形信息通常是以矢量图或者位图的形式存储的。

位图字体:就像一张张小小的点阵图,每个汉字的字形都由一个固定大小的像素矩阵组成。这种字体在显示时简单直接,但在放大时容易失真,边缘会变得模糊或出现锯齿。
矢量字体(如TrueType、OpenType):这种字体不直接存储像素点,而是用数学公式来描述字形的轮廓。这就像用一根画笔,通过曲线和直线来勾勒出汉字的形状。优点是无论如何放大,字形都能保持清晰锐利,因为电脑会根据公式实时计算并渲染出字体的边缘。我们现在看到的绝大多数高质量的显示字体都属于矢量字体。

渲染的过程:显卡和显示器的工作

当我们打开一个文档,需要显示汉字时,操作系统会告诉显卡(图形处理器):“请显示这个文档,其中包含这些汉字。”

1. 读取编码:操作系统从文件中读取汉字对应的内码(比如UTF8编码)。
2. 查找字形:操作系统通过字体文件(例如,系统默认的宋体),根据汉字的内码找到其在字库中的字形描述(无论是位图还是矢量图的数学描述)。
3. 像素化渲染:显卡接收到这些字形信息后,会根据字的形状和大小,将其“绘制”成屏幕上的像素点。如果是矢量字体,显卡会根据数学公式计算出字体的边缘,然后填充颜色,形成我们看到的清晰的字形。如果是位图字体,则直接将预先做好的点阵图放到对应位置。
4. 显示到屏幕:显卡将这些绘制好的像素信息发送给显示器,显示器再通过控制屏幕上的无数个小灯(像素点)发光或不发光(或者发不同颜色的光),最终在我们眼前呈现出文字的图像。

这个过程,我们称之为文本渲染。

流程串联起来看:

1. 输入:我们敲击键盘,输入法软件捕捉按键,将其翻译成汉字的“内码”。
2. 存储:这个内码被保存到文件中,成为文件内容的一部分。
3. 输出:当我们打开文件时,操作系统读取内码,查找对应的字体文件,然后将字形信息交给显卡进行渲染,最终显示在屏幕上。

所以你看,这小小的汉字能在电脑里这么顺畅地传输和显示,背后是编码、输入法、字库、显卡等一系列复杂但又协同工作的系统支撑。从我们输入的每一个按键,到存储在硬盘里的二进制数据,再到最终跃然纸上的字形,这中间经历了无数次的“翻译”和“描绘”,但这一切对我们来说,都是瞬间完成的,就像魔法一样自然。而这背后,是无数工程师和科学家们辛勤的智慧结晶。

网友意见

user avatar

要理解汉字是如何被计算机处理的,首先就要理解编码原理。

其实不光汉字;实质上,计算机内部的一切符号都要借助编码来输入输出。


千字文
作者:周興嗣 南梁
天地玄黃 宇宙洪荒 日月盈昃 辰宿列張 寒來暑往 秋收冬藏 閏餘成歲 律召調陽 雲騰致雨 露結爲霜 金生麗水 玉出崑岡 劍號巨闕 珠稱夜光 果珍李柰 菜重芥薑 海鹹河淡 鱗潛羽翔 龍師火帝 鳥官人皇 始制文字 乃服衣裳 推位讓國 有虞陶唐 弔民伐罪 周發殷湯 坐朝問道 垂拱平章 愛育黎首 臣伏戎羌 遐邇壹體 率賓歸王 鳴鳳在樹 白駒食場 化被草木 賴及萬方 蓋此身髮 四大五常 恭惟鞠養 豈敢毀傷 女慕貞絜 男效才良 知過必改 得能莫忘 罔談彼短 靡恃己長 信使可覆 器欲難量 墨悲絲淬 詩讚羔羊 景行維賢 克念作聖 德建名立 形端表正 空谷傳聲 虛堂習聽 禍因惡積 福緣善慶 尺璧非寶 寸陰是競 資父事君 曰嚴與敬 孝當竭力 忠則盡命 臨深履薄 夙興溫凊 似蘭斯馨 如松之盛 川流不息 淵澄取映 容止若思 言辭安定 篤初誠美 慎終宜令 榮業所基 籍甚無竟 學優登仕 攝職從政 存以甘棠 去而益詠 樂殊貴賤 禮別尊卑 上和下睦 夫唱婦隨 外受傅訓 入奉母儀 諸姑伯叔 猶子比兒 孔懷兄弟 同氣連枝 交友投分 切磨箴規 仁慈隱惻 造次弗離 節義廉退 顛沛匪虧 性靜情逸 心動神疲 守眞志滿 逐物意移 堅持雅操 好爵自縻 都邑華夏 東西二京 背邙面洛 浮渭據涇 宮殿盤鬱 樓觀飛驚 圖寫禽獸 畫彩仙靈 丙舍傍啟 甲帳對楹 肆筵設席 鼓瑟吹笙 升階納陛 弁轉疑星 右通廣內 左達承明 既集墳典 亦聚羣英 杜稾鍾隸 漆書壁經 府羅將相 路俠槐卿 戶封八縣 家給千兵 高冠陪輦 驅轂振纓 世祿侈富 車駕肥輕 策功茂實 勒碑刻銘 磻溪伊尹 佐時阿衡 奄宅曲阜 微旦孰營 桓公匡合 濟弱扶傾 綺迴漢惠 說感武丁 俊乂密勿 多士寔寧 晉楚更霸 趙魏困橫 假途滅虢 踐土會盟 何遵約法 韓弊煩刑 起翦頗牧 用軍最精 宣威沙漠 馳譽丹青 九州禹跡 百郡秦并 嶽宗恆岱 禪主云亭 雁門紫塞 雞田赤城 昆池碣石 鉅野洞庭 曠遠緜邈 巖岫杳冥 治本於農 務茲稼穡 俶載南畝 我藝黍稷 稅熟貢新 勸賞黜陟 孟軻敦素 史魚秉直 庶幾中庸 勞謙謹敕 聆音察理 鑑貌辨色 貽厥嘉猷 勉其祗植 省躬譏誡 寵增抗極 殆辱近恥 林皋幸即 兩疏見機 解組誰逼 索居閒處 沈默寂寥 求古尋論 散慮逍遙 欣奏累遣 慼謝歡招 渠荷的歷 園莽抽條 枇杷晚翠 梧桐早凋 陳根委翳 落葉飄颻 游鵾獨運 凌摩絳霄 耽讀翫市 寓目囊箱 易輶攸畏 屬耳垣牆 具膳餐飯 適口充腸 飽飫烹宰 飢厭糟糠 親戚故舊 老少異糧 妾御績紡 侍巾帷房 紈扇圓潔 銀燭煒煌 晝眠夕寐 籃筍象牀 弦歌酒讌 接杯舉觴 矯手頓足 悅豫且康 嫡後嗣續 祭祀烝嘗 稽顙再拜 悚懼恐惶 箋牒簡要 顧答審詳 骸垢想浴 執熱願涼 驢騾犢特 駭躍超驤 誅斬賊盜 捕獲叛亡 布射遼丸 嵇琴阮嘯 恬筆倫紙 鈞巧任釣 釋紛利俗 並皆佳妙 毛施淑姿 工顰妍笑 年矢每催 曦暉朗耀 琁璣懸斡 晦魄環照 指薪脩祜 永綏吉劭 矩步引領 俯仰廊廟 束帶矜莊 徘徊瞻眺 孤陋寡聞 愚蒙等誚 謂語助者 焉哉乎也

比如,我们可以用这篇千字文作为编码依据,写出数字1,就对应于天;写出数字2,就对应于地……那么,我们就可以用最多四位数字把所有这些字表示出来。

然后,如果咱组织个天地会的话,就可以用数字1 2作为接头暗号;或者,更中二一点——左手一个指头指天,右手两个指头指地……

更精细点的话,我们可以把每个手指的伸曲作为不同的编码;那么两只手10根手指就能编码1024个不同文字——左手伸一下拇指,收回;然后再伸一下食指……

接头人一看:哎呀同志!可算找到组织了!


咳咳。

总之,我们看到了,文字是可以用其它方式“曲折隐晦”的表达的。

既然手指的伸曲可以作为一个不同的状态、使得我们一双手伸20次就能吟咏完这首诗:

白日依山尽,黄河入海流。 欲穷千里目,更上一层楼。


那么,用10根电线的不同通电状态组合,是不是也能编码这篇千字文?


没错。这就是数字电路原理。

我们把电线有电叫做状态1,电线没电叫做状态0;于是,00000 00001就是一个状态,而00000 00010是另一个状态——规定每个位的电信号权值为2^n,其中n是第n条电线,从0开始编码:这就是二进制数字。


二进制拿来记录处理电路状态实在太方便了;因此,计算机里面习惯用二进制描述电路状态。比如,寄存器当前值是00000 11000、地址线收到一个信号00100 11011,等等。

请记住,这并不是说电路里神奇的出现了0和1,而是我们把电路断开(无电)叫0、电路闭合(有电)叫1,从而可以用0/1组成的数字串简洁的把“一把导线里面每根线的电压状态”表示出来。


如果不明白的话,请反复诵读这句话:00100 11011 应该读作 断断通断断 通通断通通。


二进制用起来还是不够方便。

事实上,按照每位的权值是2^N的规则(和十进制计数法每位权值是10^N一模一样),我们可以很容易的把它转换为十进制表示——注意只是表示。

比如,电路状态 断断通断断 通通断通通,对应的二进制表示为00100 11011,十进制表示为155,十六进制表示为98——表示成十进制、十六进制短了很多,方便记忆了;但却不再能直观的看出电路的通断状态:必须转换回2进制,才知道这个状态是 断断通断断 通通断通通。

但对我们要处理汉字的人来说,电路状态我们并不关心;只要能够区分它、从而把它和一个汉字对应起来就行了。因此我们一般直接用16进制(方便和二进制互换),不用二进制。


总之,这个状态是电路上实实在在的物理状态,拿万用表可以测出来。我们把这个东西叫做机内码。


所谓编码,就是把千字文、阿拉伯数字以及康熙大字典中的每一个字对应到机内码的过程。

比如,空格" "对应于十进制的32、十六进制的20以及二进制的00100000;阿拉伯数字"1"则对应于十进制的49、十六进制的31以及二进制的00110001……以此类推。


可以看出,这个编码可以是一个极其随意的过程。

比如,我很随意的用千字文编码;但发明计算机的美国佬却用ASCII码先编码了英文字母、阿拉伯数字以及!@$#^%之类符号 ;其它各国在引进计算机时,也会自说自话的搞出自己的编码方案、从而把本国语言文字输入计算机……

比如,我国就有GB2132、GBK、GB18030等汉字编码;但台湾、日本、韩国以及东南亚国家也用汉字,他们也搞了个另外的好多套编码……


那么,这一大堆编码方案,谁说了算?

不然的话,按你的编码,99 67 54是520,结果到法国佬那里成了250……你们还不要打起来啊?


所以,现在搞了一个全球统一的Unicode码,一网打尽全球所有语言。


编码完成之后,汉字就可以和罗马字母、法文字母、德文字母、俄文字母、英文字母一样,以电信号有无/磁化方向/光盘上的凹坑等等不同状态存储起来了。


其中,在光盘上时,它是一串凹坑的组合;在硬盘上,它是一组磁畴的磁化方向;在内存条里,它是场效应管的充电状态;在并行总线上,它是一把金属导线的电压高低组合;在串行通讯线缆上,它是高高低低的一组方波……


所有这些状态,都可以用二进制表示;所有这些二进制,都可以转换成更方便阅读和记忆的十进制/十六进制数字——但想要直观的理解电路状态,都必须还原到二进制。


我们知道,键盘上面只有26个英文字母以及十个数字和!@#$% 等特殊符号,以及tab、shift、enter等控制键(但也可以用来输入)……


你看,没有汉字啊?这怎么办?


事实上,键盘输入,归根结底也只是电信号而已。

既然我们已经用abcd、1234等等编码了这些电信号;那么,把这些电信号翻译回12345、然后直接用12345这些按键上的字符、拼凑出每个汉字的Unicode码——这,不就解决了输入问题吗?

这个自动把键盘敲的字母组合翻译成对应的汉字的程序,就是我们熟悉的输入法。


嗯。别急,别急。我知道你记不住。没人能记住超过六万个汉字的Unicode编码。所以并没有这样的输入法。


虽然这个办法的确行不通;但这个思路是成立的,对吧?

既然思路成立,那么不要急,一步一步来。先找出问题,再一步步解决它。


现在的问题在于,用这种方法敲汉字,我们第一记不住编码表,第二只能利用数字小键盘,输入效率太低。

怎么办呢?

没错。拼音。我们把二十六个英文字母当拼音,把每个汉字的读音敲进去,不就好了?


没那么简单。普通话一共才几百个音,汉字六万多……同音字实在太多了。这怎么输入?


没错。笔画输入。汉字归根结底有五种基本笔画,横竖撇捺折对应12345,妥了——比如王字怎么写?横横竖横,1121,哈哈搞定。


仍然不行。遇到工字和土字,你怎么办?


所以现在的问题是重码,对吧?

好办。把重码字列出来,给用户选择。这下妥了吧?


没错。解决了。

甚至于,拼音输入也能这样解决。

不仅如此,既然普通话只有几百个音,那没必要敲全eng、ang吧?

给eng/ang也来个编码,敲两下,一个音就进去了——哈哈,双拼!


但这样仍然不好用。每敲一个字都要在候选字里面找半天,这实在太慢了。


还得继续优化。

现在有两个思路。

一是王永民先生搞的五笔输入法,思路是从编码汉字的偏旁部首入手设计一套字根表,一方面减少了每次输入的击键次数,另一方面减少乃至杜绝了重码。以至于五笔高手可以轻易做到每分钟输入超过200个汉字。

但五笔输入法需要专门的训练。背字根表,反复练习直到形成肌肉记忆……

因此,另一条思路获得了更多支持,以致于现在只有专业录入人员才会学习五笔。

这个思路就是:继续使用拼音输入法;但尽量让用户一次输入一个词、一句话;那么借助软件强大的分析能力,就可以“猜”出他最可能想说什么。

打个比方的话,你说“lin”,没人知道是哪个字;但你说“树林”“林黛玉”“临安”“临颍”“淋雨”,这个字就唯一确定了。

当然,单字仍然无法确定;有些词也有同音。但无论如何,这个策略使得重码少了很多。尤其借助概率论的马尔科夫链理论,整句输入可以得到极高的准确率,几乎不用选字,从而使得熟练的拼音使用者也能一分钟输入一百字以上。


总之,汉字的输入是一个编码的嵌套过程:先是击键产生一个键盘码,键盘码被键盘内置的CPU转换成对应的ASCII机内码(并行线路是通断错落的一组电平,串行线路是一组方波);然后这些ASCII码的组合(比如ABCD)又被转换到汉字机内码(Unicode或者GB2312/GBK/GB18030)——最终,这些机内码被保存到磁盘/光碟等存储介质,汉字从输入到储存这一条龙过程就算走完了。


注意这里面反复进行了多次编码和解码;但编码/解码过程各自独立,互不影响。

比如,你可以用拼音或者五笔编码汉字、然后以这个编码输入;然后输入法解码你敲入的键盘字符序列,再自动帮你编码到Unicode或者GB系列。

从哪个途径转换我们不需要关心。只要最终得到的Unicode正确。


编码和存储搞定了,怎么输出呢?

比如,见了12354这串数字,你怎么知道它应该是哪个汉字?这个汉字该怎么写?


在回答这个问题前,我们应该先想一想:屏幕上是如何显示汉字的?

我们知道,屏幕是由一个个像素构成的。正如我对着自己显示器拍的这张照片,像素的不同取值就构成了汉字的笔画,最终组成我们见到的汉字。


那么,像素的黑白,岂不是也可以用0和1编码吗?

没错,这就是点阵字体:

正字的Unicode编码是十六进制的6B63,而6B63这个机内码关联到一副bitmap(位图),这张位图也可以用二进制编码,就是上图右侧那那一堆数字——按顺序存下来,就是正字的16位点阵。

类似的,还可以搞32位或更大的点阵,从而把字体显示的更精确一些。


总之,六万多汉字就对应着6万张不同的点阵图片。

我们知道,汉字有不同的字体。比如楷书、隶书、宋体、仿宋,等等。这些就对应着不同的小图片。

因此,每个不同字体又对应着不同的六万张小图片,你装了100种字体,电脑里就有了六百万张不同的图片。


将来,当需要显示汉字时,从Unicode找到对应的图片(也就是那一堆二进制串),再按照指示给显示器不同的像素通电/断电,于是显示器上就黑白分明的显示了不同汉字。


当然,显示器的显示原理也各不相同。比如,CRT是电子束轰击荧光粉,没有电子轰击的地方就不发光;而LCD呢,哪里通电“搅乱”的液晶,哪里就混浊不透光;LED,哪个发光管通电哪个发光……

因此,具体显示时,显示器也还需要“翻译”一下。比如CRT遇到0就改变电子枪栅极电压,不让电子飞出去;而LCD遇到0就切断对应像素的电压输出,让液晶恢复透明……


不仅如此。

不同显示屏尺寸不同、每英寸像素数也大相径庭。32点阵的汉字,在某些屏幕上占地太大,一屏显示不了几个;但在视网膜屏上又显得太小,拿放大镜才看得见……

怎么办呢?

的确可以通过插值的方式缩放;但这样效果并不好(插值是一种通过算法自动添加像素的方式,比如正字放大一倍显示时,就要把横从一排像素改成两排;但如果缩放不是整数倍、或者笔画弯折处就很难确定该不该插入像素)。


另一种方式是,不记录像素,记录“写字过程”。比如线条从哪里起始、在哪里转折、到哪里结束,以及哪里下笔重、哪里下笔轻,等等。

这就是所谓的“矢量字体”,它记录的是笔画线条以及转折、粗细等信息,因此可以非常方便的缩放。


不仅如此。你可能注意到,我拍摄的实际屏幕照片里,“评论”二字笔画边缘颜色有些发暗。

这是clear type处理后的结果。经过这个处理后,字体看起来笔画更光滑、更锐利、更美观。


换句话说,字符输出并不像想象那么简单。它可能需要矢量图缩放、点阵图转换、cleartype/truetype之类技术处理点阵图(注意这里是彩色点阵,这种点阵里,每个像素又分为红绿蓝三个分量,每个分量又有256级亮度),然后才能照图施工、把文字输出到屏幕上。


这就是汉字输入输出的全过程。

类似的话题

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有