Java技术分享

Unicode和Java中所使用的Unicode编码的问题

2018-09-04  本文已影响0人  Belmode

本文为Belmode原创,转载请声明。
文中如有错疏,还望指正。喜欢本文可以收藏,或者关注,更新文章即时阅读!

众所周知,“Unicode编码占两个字节”。相信很多人都 这么认为。但是如果深入的理解什么是unicode之后就会知道,Unicode编码占两个字节存在一定问题,今天跟大家简单聊聊Unicode。

什么是Unicode?

unicode是一个标准,也可以说是世界上的语言字符和数字映射的一种标准。它没有限制字符的数量,但是可能这个标准规定的映射只是映射了一部分字符。每个字符映射一个code point(码点)。Unicode 目前规划的总空间是17个平面(平面0至16),0x0000 至 0x10FFFF。每个平面有 65536 个码点。

所以Unicode支持的字符上限是65536个 这句话也是有问题的,这65536个字符是我们最常用的基本字符,但是还有很多字符是在0x0000--0xFFFF之外的。
在我们说unicode是几个字节这句话的时候,就已经暗示了我们现在讨论的是unicode在计算机内存里的存储方式了(只有在计算机系统里才有字节这种定义,如果脱离计算机的话unicode是不会与字节扯上关系的)。
unicode存储在计算机内存里肯定是需要编码的,那么就有UTF-8,UTF-16,UTF-32等编码方案。
为什么我们常说“unicode字符是2个字节”,是因为windows默认的unicode编码就是UTF-16。而unicode在这种编码下,大部分都是2个字节的,至少上面提到的前65536个基本常用字符都是2个字节的。
所以就有了“unicode字符是2个字节”这句话。其实UTF-16是一种变长的编码方案,有些unicode字符的抽象码点(code point)编码后是2个字节,有些是4个字节。
所以“unicode字符是2个字节”这句话大多数时候是正确的,但是unicode字符的抽象码点(code point)超过范围0x0000--0xFFFF后就不对了。而0x0000-0xFFFF正是unicode基平面

在表示一个Unicode的字符时,通常会用“U+”然后紧接着一组十六进制的数字来表示这一个字符。在基本多文种平面(英文为 Basic Multilingual Plane,简写 BMP。它又简称为“零号平面”, plane 0)里的所有字符,要用四位十六进制数(例如U+4AE0,共支持六万多个字符)在零号平面以外的字符则需要使用五位或六位十六进制数了。旧版的Unicode标准使用相近的标记方法,但却有些微的差异:在Unicode 3.0里使用“U-”然后紧接着八位数,而“U+”则必须随后紧接着四位数。

UTF-16特殊点

一些关于Unicode的细节,例如大小端、代理方式就不再这里赘述、细说了。具体可以参考度娘词条 Unicode
平面0也有一个专用区:0xE000-0xF8FF,有6400个码位。平面0的0xD800-0xDFFF,共2048个码位,是一个被称作代理区(Surrogate)的特殊区域。代理区的目的用两个UTF-16字符表示BMP以外的字符。这就是为什么两个字节可以表示4个字节的字符!

Java中的Unicdoe

Java字符串内存中以Unicode形式存在,再具体一点应该是UTF-16这种格式。
而在源文件编译文件中,字符串则可以以各种(操作系统)可支持的编码形式存在。
简单的说,存在文件中的字符串是多种编码的,在它们被装载到内存时,都转换成了UTF-16的编码,所以说Java中字符串是统一编码的,这个统一是指在内存中统一。
另外,标准的Unicode占用的是4字节,并不是2字节,Java采用的UTF-16是优化存储后的Unicode,`UTF-16对于常规字(包括全世界各种语言的文字)都可以以2字节存储,
当然也有一些不在常用字范围的东西(在Unicode字符平面中靠后的)需要用4字节来存储,比如Emoji表情符号等。

要注意的是,优化存储,就是被代理的结果。

上一篇下一篇

猜你喜欢

热点阅读