以JS处理emoji表情为例简介UTF-8编码

文章推薦指數: 80 %
投票人數:10人

以JS处理emoji表情为例简介UTF-8编码. Emoji 表情符号是直接保存在字符中的标签,不是一张图片,而是可以理解为和一个汉字同类的东西。

因此在绝大多数可以打字的地方, ... archivedtech以JS处理emoji表情为例简介UTF-8编码 Emoji表情符号是直接保存在字符中的标签,不是一张图片,而是可以理解为和一个汉字同类的东西。

因此在绝大多数可以打字的地方,就能放Emoji。

但是某些地方会出现表情变成问号或者一个框框的情况,其中一个可能的原因是使用了自定义的,或者过时的UTF-8解码形式。

首先简单说明一下文字在计算机中是如何被存储的。

毫无疑义的是,文字最终一定是以二进制的形式存储的。

其中最简单的是著名的ASCII码,他是早期由美国指定的一个编码标准,建立了一个二进制数到字母和符号的映射关系,其中共有128个符号,包括了英文大小写字母和标点符号等。

二进制范围从00000000到01111111,具体范围可以查看维基百科。

后来互联网时代这套标准延续了下来,一直用于英语文字的存储,通常直接用8位二进制,即一个字节(Byte)存储。

可是问题来了,世界并不只有英文,欧洲有法语、德语等语言不全是有26个英文字母组成的,亚洲又有众多的象形文字,比如中文字符的数量就多了去了。

所以继续拓展,一开始,欧洲国家使用一个字节中剩下的128个空间各自表示自己语言的符号,而中文则是以GB2312为主(如Windows系统),用两个字节来存储常用的6万多个汉字。

由于各种编码之间并不是遵循同样的标准,所以有些时候我们会看到各种乱码,比如著名的手持两把锟斤拷,口中直呼烫烫烫。

Unicode与UTF-8 Unicode的出现,正是为了解决文字编码问题,它建立了一张超大的映射关系表,存储各国文字符号,可以看作是ASCII的国际版,其数量已经远远超过了2个字节的范围。

其中Emoji表情就在其中占有一段位置。

那么为什么有了Unicode还会出现乱码和Emoji的不正常显示呢?因为Unicode只是规定了映射关系,具体存储并不一定按照这个顺序直接对应到二进制码。

除了历史原因外,还有一个问题就是长度过长引起的浪费,假设用3个字节作为一个文字符号,那么英语(ASCII)的存储就会出现两个字节的浪费。

因此通常采用一种可以兼容ASCII的存储方式,使得字节数不需要固定到最大位数。

著名的UTF-8便是Unicode的一种实现方式,解决了上面提到的长度浪费问题。

除去ASCII的范围,一个字节中还存在1开头的各种情况,UTF-8充分利用了这部分空间,规定了一些标识位,实现了变长的编码方式,即一个字符可能由1-4个字节组成。

这样ASCII继续保持精简,而其他丰富的符号则自行拓展更多的字节保存。

编码规则十分简单,见下表 Unicode符号(顺序、16进制表示) UTF-8编码(变长、2进制表示) 00000000-0000007F 0xxxxxxx 00000080-000007FF 110xxxxx10xxxxxx 00000800-0000FFFF 1110xxxx10xxxxxx10xxxxxx 00010000-0010FFFF 11110xxx10xxxxxx10xxxxxx10xxxxxx 解码规则总结:对于每一个字节 如果第一位为0,则为单字节码,后面7位表示ASCII 如果开头为110,则表示双字节码的第一个字节,其后5位及下一个字节的后6位共同组成一个Unicode符号 如果开头位1110,则表示三字节码的第一个字节 如果开头位11110,则表示三字节码的第一个字节 Emoji编解码 Emoji在Unicode的位置比较靠后,通常需要4个字节码。

因此如果解码方案里面没有考虑4个字节的情况(11110开头),则会出现一些混乱,但是混乱不会影响太多,因为假设只解析了3个字节,那么最后一个字节是10开头,通常会被忽略。

下面以JS为例,进行Emoji的编码。

functionstringEncode(str){ constbytes=newUint8Array(str.length*4);//先都假设最长 letoffset=0; for(leti=0;i0xc0,00111111->0x3f,0x80->10000000 codes=[0xc0|(charCode>>6),0x80|(charCode&0x3f)]; }elseif(charCode<=0xffff){//三字节111111000000->0xfc0 codes=[0xe0|(charCode>>12),0x80|((charCode&0xfc0)>>6),0x80|(charCode&0x3f)]; }else{//四字节111111000000000000->3f000 codes=[ 0xf0|(charCode>>18), 0x80|((charCode&0x3f000)>>12), 0x80|((charCode&0xfc0)>>6), 0x80|(charCode&0x3f) ]; } for(letj=0;j



請為這篇文章評分?