java代码点与代码单元 java代码点与代码单元的区别
java什么是代码点和代码单元
说白了一个代码点就是一个Unicode字符。代码单元就是代码点的集合。
成都创新互联公司服务项目包括白朗网站建设、白朗网站制作、白朗网页制作以及白朗网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,白朗网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到白朗省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!
字符视图
要了解字符集标准,您必须能区分三种不同的字符视图:
字符集(字符的抽象列表)。
作为带标量值的“代码点”的字符。
作为编码数据的字符。
字符集(字符的抽象列表)
字符集是各种文字(包括拉丁文、西里尔文、中文、朝鲜语、日语、希伯来语和阿拉伯语)中所包含的字符的一个抽象列表,由一百多万个字符组成。字符集还包括其他符号,例如音符。
Unicode 和 GB18030 标准都具有字符集。当某个标准添加了新字符时,为了保持对等,另一个标准也将添加这些字符。
作为带标量值的“代码点”的字符
注意 这第二个字符视图只适用于 Unicode,而不适用于 GB18030。
字符集中的每个字符都被分配到一个“代码点”。每个代码点都有一个特定的数值,称为标量值。该标量值通常用十六进制表示。
代码点存在于“代码空间”中。代码空间由许多标量值组成,这些值被划分在两个平面中:
基本多语种平面(64k 大小)。
在 Unicode 中,此下平面中的值的十六进制表示位于 U+0000 到 U+FFFF 的范围中。
辅助多语种平面(16 个 64k 大小的附加节)。
在 Unicode 中,此上平面中的值的十六进制表示位于 U+10000 到 U+10FFFF 的范围中。
所有可能的标量值的完整代码空间的大小为 17 * 64k(1,088,000 个可能值)。
作为编码数据的字符
每个编码形式将字符从字符集转换为编码数据。
在 GB18030 中,编码数据直接从字符集派生:标量值(作为字符集和编码数据之间的媒介)的概念只适用于 Unicode。
在 Unicode 中,通过向标量值应用某个算法来派生编码数据。
Unicode 定义了三种字符编码形式:
UTF-8
UTF-16
UTF-32
代码点和代码单元
在每种编码形式中,代码点被映射到一个或多个代码单元。
注意 有关代码点的概述,请参见上一节字符视图。
“代码单元”是各个编码形式中的单个单元。代码单元的大小等效于特定编码的位数测量单位:
UTF-8 中的代码单元由 8 位组成。
UTF-16 中的代码单元由 16 位组成。
UTF-32 中的代码单元由 32 位组成。
GB18030 中的代码单元由 8 位组成。
每个代码点中的代码单元数
映射到代码点所需的代码单元数根据编码形式而有所不同:
UTF-8
在 UTF-8 中,因为代码单元较小的缘故,每个代码点常常被映射到多个代码单元。代码点将被映射到一个、两个、三个或四个代码单元。
UTF-16
UTF-16 的代码单元大小是 8 位代码单元的两倍。所以,标量值小于 U+10000 的代码点被编码到单个代码单元中。
对于标量值大于或等于 U+10000 的代码点,每个代码点需要两个代码单元。在 UTF-16 中,这些代码单元对有一个独特的术语:“Unicode 代理对”。
注意 下面对 Unicode 代理对的支持进行了讨论。
UTF-32
UTF-32 中使用的 32 位代码单元足够大,每个代码点都可编码为单个代码单元。
GB18030
在 GB18030 中,因为代码单元较小的缘故,每个代码点常常被映射到多个代码单元。代码点将被映射到一个、两个或四个代码单元。
对 Unicode 代理对的支持
某些受 Unicode 支持的文字包含代码点的标量值大于或等于 U+10000 的字符。在 UTF-16 中,通过使用代理对来对这些代码点进行编码。
正确处理 Unicode 代理对非常重要。例如,当您在使用 UTF-16 编码的应用程序中处理文本时,如果要添加、删除或选择字符以进行剪切、复制或粘贴操作,文本光标必须将每个代码点作为单个文本字符导航。
Java中代码点和代码单元是什么?怎么理解?举例说明下,它们之间有什么联系有什么区别?为什么代码点
代码点就是指javascript型的信息点而代码单元指普遍的广泛的jinmk 和gdp信息技术网
关于Java核心技术书中的代码点和代码单元是怎么理解的呢?
这些应该是从Unicode标准而来的术语,Unicode标准的核心是一个编码字符集,它为每一个字符分配一个唯一数字。Unicode标准始终使用16进制数字,并且在书写时在前面加上U+,如字符“A”的编码为“U+0041”。
代码点是指可用于编码字符集的数字。编码字符集定义一个有效的代码点范围,但是并不一定将字符分配给所有这些代码点。有效的Unicode代码点范围是U+0000至U+10FFFF。Unicode4.0将字符分配给一百多万个代码点中的96382个代码点。
代码单元可以理解为字符编码的一个基本单元,最常用的代码单元是字节(即8位),但是16位和32位整数也可以用于内部处理。
就Unicode标准来说,它的编码字符集有三种编码方案:UTF-32、UTF-16、UTF-8。UTF-32使用32位的代码单元表示一个Unicode代码点,UTF-16使用一个或两个16位的代码单元的序列对Unicode代码点进行编码,UTF-8 使用1至4个字节的序列对Unicode代码点进行编码。
winhex8位反向字节的顺序
一、char 码点和代码单元
在Java Core 卷1中 对Char的描述如下
在设计Java时决定采用16位的Unicode字符集....(中间省略)... 现在16位的Char类型已经不能满足描述所有Unicode字符的需要了。
Java为了解决这个问题的方法是使用码点和代码单元
代码点(Code Point):在 Unicode 代码空间中的一个值,取值 0x0 至 0x10FFFF,代表一个字符。
代码单元(Code Unit):在具体编码形式中的最小单位。比如 UTF-16 中一个 code unit 为 16 bits,UTF-8 中一个 code unit 为 8 bits。一个 code point 可能由一个或多个 code unit(s) 表示。在 U+10000 之前的 code point 可以由一个 UTF-16 code unit 表示,U+10000 及之后的 code point 要由两个 UTF-16 code units 表示
在Java中,char类型描述了UTF-16编码中的一个代码单元
码点:就是某个任意字符在Unicode编码表中对应的代码值代码单元:是在计算机中用来表示码点的,大部分码点只需要一个代码单元表示,但是有一些是需要两个代码单元表示的。
不同码点对应的代码单元数量可能不同
下面实际操作体验一番
" " 这个数学符号码点 为U+1D546 在 Java中的代码单元为 U+D835 和U+DD46
String word = "uD835uDD46";
System.out.println("字符为:"+word + " String.length(): "+ word.length());
打印结果如下(String.length()返回的是字符串代码单元的长度)。
字符为: String.length(): 2
而且char类型无法放下这个符号
//char c = ' ';
String word2 = " ";
String firstUnit = Integer.toHexString(word.charAt(0));
String secondUnit = Integer.toHexString(word.charAt(1));
String codePoint = Integer.toHexString(word2.codePointAt(0));
System.out.println("第一个单元:" + firstUnit + " 第二个:" + secondUnit + " 码点:" +codePoint);
打印结果
第一个单元:d835 第二个:dd46 码点:1d546
二、UTF-16编码方式
我们来思考UTF-16的设计思路:
我们知道Unicode的范围为0x0~0x10FFFF
首先是0x0~0xFFFF这段区间,正好16位就可以表示,也兼容,两全其美
那么超过这个区间的怎么办呢?
也就是0xFFFF~0x10FFFF这段,我们先看这段区间有多少个码位,
0x10FFFF-0xFFFF=0x100000,那么这个十六进制表示的十进制也就是:1048576个码位
我们既然16位存不下,那肯定就是32位存咯,这个32能理解为什么不?不理解?是因为计算机只能以2的倍数拓展,如果不这么设计,就没办法解析。长短不一,不符合设计思路
32位来存这些数字,那么我们需要怎么存下呢,简单的思考过后,大家认为应该分开存储,也就是将32位分开前16位和后16位,每个16位各存一半
那么每一半存的就是1024(由来:1024*1024=1048576),1024代表的是2的10次幂,也就是10位二进制数
这样就知道了,32位二进制数字中,前后16位中各存10位就够用了,但是剩余的6位用来干什么呢?
和UTF-8的设计一样,为了让识别字符串变得容易(从文本的任意位置开始,均能区分一个字符的起始),这里是不是有点儿蒙?
举个栗子:
假设:
0000 0001 代表A
0000 0010 代表B
0000 0001 ,0000 0001 代表 X
0000 0010 ,0000 0001 代表Z
那么 ABXZ就是
0000 0001 ,0000 0010 , 0000 0001 ,0000 0001 , 0000 0010,0000 0001
A B X Z
但是让你从中间开始读取,当你读到X的时候,你不知道他是X还是 AB,这样就很麻烦,你需要设置标志,来让16位的数据的前8或后8不会和单个8位的重复
可以这样设计:
0xxx xxxx 代表0~2^7
11xx xxxx ,10xx xxxx 代表其他的
这样就能区分开了,当你读到11开头的,就代表他是16位的前8,10开头代表16位的后8
欧了,有了这个思路,我们就知道怎么设计刚才的那个6位了,当然是通过这6位来区分这16位数字代表的位置
也就是UTF-16中,表示数据有单16位和双16位(32位)两种,那么我们设计成单16位和32位中的前16位和后16位这三个16位完全不会重复,那么我们就能随时读到一组16位,就能知道他是单16还是前16还是后16
举个栗子:
根据上方信息,要求我们通过前6位来区分数据,那么前6位就是2^6=64,也就是开头数字的区间
我们设定如下:
54开头的为32位的前16位
55开头的为32位的后16位
其他开头的为单16位
这样我们就能区分开这三个16位了,在读取文档中的任意位置,都能随意区分出间隔咯
那么54开头的数据区间是多少呢,就是1101 10xx xxxx xxxx,区间就是D800~DBFF
那么55开头的数据区间是多少呢,就是1101 11xx xxxx xxxx,区间就是DC00~DFFF
为了配合UTF-16,Unicode中也将这两个区间屏蔽掉,不允许分配任何字符
下方为比较官方的关于UTF-16的编码详解
参考文献:
具体编码方式
Unicode范围U+10000~U+10FFFF:将Unicode值减去(0x10000),得到20bit长的值。再将Unicode分为高10位和低10位。UTF-16编码的高位是2 Byte,高10位Unicode范围为0-0x3FF,将Unicode值加上0XD800,得到高位代理(或称为前导代理,存储高位);低位也是2 Byte,低十位Unicode范围一样为0~0x3FF,将Unicode值加上0xDC00,得到低位代理(或称为后尾代理,存储低位)
根据上面的转换方式,我们就能够将Unicode码根据UTF-16的编码方式进行转换。下面我们仍然通过两个例子来看下:
U+0020,这个值的范围在第一部分,即经过UTF-16编码后,结果仍然为U+0020,在内存中的顺序为00 20。
U+12345, 这个值的范围在第二部分,因此需要先减去0x10000,得到0x02345,拆分成高10位00 0000 1000和低10位11 0100 0101。根据上面规则加上特定值后,高位代理值为D808,低位代理值为DF45,最终内存中的顺序为D8 08 DF 45。
本文标题:java代码点与代码单元 java代码点与代码单元的区别
网页路径:http://azwzsj.com/article/doipjdi.html