操作系统、输入法和编码的理解

操作系统和输入法

操作系统有一个输入法管理器,叫做IMM,管理系统内的所有输入法,或者说一个输入法想要使用操作系统提供的输入法API,就必须在IMM进行注册。

应用程序和输入法

应用程序一般都会使用输入法,也就是调用输入法的api进行文字输入。比如你想要使用文本编辑器txt保存“我爱你”三个字,那么打开txt的时候,txt会通过操作系统来调用某个输入法,具体调用哪个输入法取决于当前系统和用户设置。

字符集和编码

字符集和编码很容易混淆。其实是有区别的。
字符集的概念:顾名思义,就是字符的集合,并且每个字符都存在一个编号,编号也称为码点,字符集有时称为码表。比如ASCII字符集包含了128个字符。字符”空格“在ASCII中为第一个字符,因此它的ASCII编号为0,字符”1“为第49个字符,因此”1“的编号为49。同理Unicode也是一个字符集,包含了世界上所有的字符,并且每一个字符都有对应的编号。中文 ‘中’字,在Unicode字符集中为第20013(十进制)个字符,因此编号为20013(十进制),十六进制为4E2D

编码:只有当涉及到存储或者传输的概念时,才涉及到编码,计算机内存中处理数据一般使用编号。什么是编码呢,举个例子,想要在计算机上保存字符”1“,就必须存储它的编号49,49的二进制为110001,一共是6位二进制数,但是计算机按只能按字节来存,那么保存49就得使用八个二进制位,显而易见的方式是在前面补充0,既00110001,这个00110001也就是字符”1“的ASCII字符集中的ASCII编码(ASCII字符集中也只有这一种编码)。因此,我们必须注意编号和编码的区别。
那么,在编号前面补充0就变成编码了吗?没那么简单!
如果采用目前使用最广的Unicode字符集,若想保存字符”中“,我们知道应该保存它的编号20013(十进制),20013的十六进制为4E2D,二进制为100 1110 0010 1101 我们很容易想到使用两个字节就可以进行存储,并在前面补上一个0,变成0100 1110 0010 1101,好像看上去没问题,但是存在一些大问题。
比如:
Unicode字符集中有上百万个字符,当遇到编号为1114111的字符时,如何保存?1114111的二进制为10000 11111111 11111111,一共有21个二进制位,至少需要三个字节进行存储,补充完0后为00010000 11111111 11111111。字符“1”的Unicode编号同样为49(兼容ASCII),那么“1”只需1字节进行保存。这样问题就来了,在读取文件的时候,是一次性读1个字节还是2个字节还是3个字节呢?这无法判断,一共粗暴的解决办法是,字符“1”使用3个字节进行存储,前面两个字节用0填充,每次都按照3个字节进行读取,这样办法是可以的,UTF-32编码就是这么做的,所有字符都用4个字节进行存储。但是这样带来的问题就是过多的填充浪费存储空间。
那应该怎么根据编号进行编码呢?于是出现了UTF-8、UTF-16、UTF-32多种编码方式。详情略。

编码本质上是对码位(字符集中的编号)的编码,解码是由编码转换成码位的过程。

输入法的原理和功能

输入法的原理很简单,就是监听键盘输入,然后生成对应的字符,比如当用户输入模式为中文的时候,监听到键盘输入了"w",那输入法会弹出可选的文字框:
在这里插入图片描述如果如果监听到用户输入了2,输入法可以获取操作系统使用的字符集,如果操作系统使用Unicode字符集,那么输入法就产生了“为”这个字符的Unicode编号4e3a(16进制),然后把4e3a发送给操作系统,操作系统再给应用程序。

应用程序的编码

应用程序收到了4e3a,对4e3a进行编码然后才能保存, 具体使用什么编码这取决于应用程序的上下文设置,每个应用程序都有自己的编码或者默认编码,比如txt采用系统的默认编码,idea可以在右下方选择操作系统、输入法和编码的理解_第1张图片
若应用程序采用UTF-8编码,4e3a对应中文“为”,UTF-8编码下中文采用三个字节进行存储,先写出4e3a的二进制01001110 00111010(前面填充0使之成为两个字节),4e3a本来为2给字节,UTF-8编码成3个字节,编码方式如下:
取出前4位在前面填充上1110变成第一个字节,既1110 0100
取出5-10位,在前面填充10变成第二个字节,既10 1110 00
取出11-16位,在前面填充10变成第三个字节,既10 1110 10
于是“为”的UFT-8编码为1110 0100 10111000 10111010,这三个字节就可以保存在硬盘上或者进行传输了。

解析文件时编码错误不可逆问题

一旦使用错误的编码进行解析,将会导致解析失败,失败的原因是解析编码和文件编码不一致将无法识别对应的一些字符,当无法识别时,常用的解决办法是使用�(UTF-8)或者?(GBK)替换,一旦替换过后,原来的二进制编码就会改变,从而无法恢复。
比如,txt文件中有一个文字“中”,使用的是gbk编码保存,根据GBK编码规则硬盘中保存的是
D6 D0,也就是11010110,11010000两个字节。 当我使用idea打开这个txt文件时,如果以UTF-8的编码格式进行读取,那么idea将会以UTF-8的规则去读取D6 D0这两个字节,然而根据utf-8的解析规则,是无法解析11010110,11010000两个字节的,UTF-8遇到无法解析的字符一律以�替代。当无法解析11010110时,为了显示这个字符,就以�来替代第一个字节11010110,同理,也会以�替代第二个字节11010000,那么idea中显示的是��而不是汉字“中”,出现了乱码。�的UTF-8编码是11101111 10111111 10111101三个字节,此时这三个字节还存在于idea的内存中,硬盘上保存的还是GBK编码的D6D0,因此如果此时在idea上以GBK编码的格式重新读取文件时,idea能够正确的解析D6 D0显示汉字“中”,但是在UTF-8格式解析下,一旦在idea上进行保存,比如添加一个“国”字,idea默认进行保存,此时idea内存中将会是�的UTF-8编码和“国”的UTF-8编码,因为进行了修改操作,idea默认进行保存,那么idea就会把内存中的数据写到原来的TXT文件上,此时硬盘中本来是GBK编码的“”中的1010110,11010000两个字节,此时就会变成�的UTF-8编码11101111 10111111 10111101三个字节,加上“国”字的三个UTF-8编码的三个字节。
因此一旦以错误的格式进行解析文件,不要进行保存!否则文件内容将会被被类似�的替换字符替换修改,无法恢复!

  • 以上仅个人理解,有错勿喷*

你可能感兴趣的:(开发语言,笔记)