7.13关于es的字符集和编码方式

2020-07-13  本文已影响0人  温岭夹糕

#先来看看一个很神奇的现象

emoji的表情的长度竟然是2???

究其原因要从es的字符集和编码方式谈起

一、ES的发展历史

JS的语言采用Unicode字符集,但是只支持一种编码方式

扫盲:utf8和utf16是unicode的一种编码方式,不是字符集,是为方便Unicode字符集方便在网络传输的一种加密方式

但是JS采用的编码方式既不是UTF8也不是UTF16,更不是UTF32,而是UCS-2

UTF32规定了每个字符串的码点使用4个字节表示即32位,虽然转换方式简单,但是十分浪费空间,ASCII编码使用 1字节,相比而言要大四倍,因此HTML5标准铭文规定网页不许使用32编码

如 U+0000 = 0x00 00 00 00  4字节

U+597D = 0x00 00 59 7D 不足的前面用0填充

这要从ES的诞生时间线说起:

1.1988年Unicode团队成立(指字符集)

2.次年1989年UCS团队成立(指字符集)

3.1990,UCS-2编码发布(指编码方式)

4.1991年两者合并字符集为Unicode(合并字符集)

5.1995Js诞生

6.1996UTF-16发布,取代UCS-2(指编码方式)

也就是说JS语言诞生的时候还没有UTF16编码!!

二、UCS-2编码的特点

UCS的开发进度快于Unicode,1990年就公布了第一套编码方法UCS-2,使用2个字节表示已经有码点的字符。

TF-8是一种变长的编码方法,字符长度从1个字节到4个字节不等。越是常用的字符,字节越短,最前面的128个字符,只使用1个字节表示,与ASCII码完全相同。

UTF-16编码介于UTF-32与UTF-8之间,同时结合了定长和变长两种编码方法的特点。它的编码规则很简单:基本平面的字符占用2个字节,辅助平面的字符占用4个字节。也就是说,UTF-16的编码长度要么是2个字节(U+0000到U+FFFF),要么是4个字节(U+010000到U+10FFFF)。

上述概括:

在Unicode中,最前面的65536个字符(包括最常见的所有字符)称为基本平面(BMP),码点(16进制)从U+0000---U+FFFF,目前共有17个平面,剩下的称为辅助平面(SMP)(U+010000到U+10FFFF)

UTF-16:当在BMP范围内的字符编码为2个字节,SMP为4个字节

UCS-2:全部二个字节,一视同仁

那么问题来了?超过2个字节的怎么处理

既然不属于UCS-2,那就当两个字符来看喽~~

再回来看刚开始提出的问题

我们使用 charCodeAt查看🎾的UTF16编码

charCodeAt() 方法返回0到65535之间的整数,表示给定索引处的UTF-16代码单元 

Unicode默认16禁止,再利用toString()转为16进制

但在——例如 Unicode 编码单元 > 0x10000 的这种——不能被一个 UTF-16 编码单元单独表示的情况下,只能匹配 Unicode 代理对的第一个编码单元

所以上面默认是第一个编码单元,完善为

即🎾的UTF16编码为4个字节的0xD83C DFBE

所以JS超过2个字节,当作两个字符来看,会把它当作 U+D83C和U+DFBE两个来看

查询Unicode编码得两个都为�

验证

这也就是为什么length会失效

仅仅只是length函数吗?

以slice为例

基本上所有的字符串函数在对4字节码点的字符串表现出奇怪的现象

虽然很少遇到但还是以防万一

总结来源:http://www.ruanyifeng.com/blog/2014/12/unicode.html

上一篇 下一篇

猜你喜欢

热点阅读