本文转自:http://www.blogjava.net/zhenandaci/archive/2009/01/05/249866.html
Java号称对Unicode提供天然的支持,这话在很久很久以前就已经是假的了(不过曾经是真的),实际上,到JDK5.0为止,Java才算刚刚跟上Unicode的脚步,开始提供对增补字符的支持。
现在的Unicode码空间为U+0000到U+10FFFF,一共1114112个码位,其中只有1,112,064 个码位是合法的(我来替你做算术,有2048个码位不合法),但并不是说现在的Unicode就有这么多个字符了,实际上其中很多码位还是空闲的,到Unicode 4.0 规范为止,只有96,382个码位被分配了字符(但无论如何,仍比很多人认为的65536个字符要多得多了)。其中U+0000 到U+FFFF的部分被称为基本多语言面(Basic Multilingual Plane,BMP)。U+10000及以上的字符称为补充字符。在Java中(Java1.5之后),补充字符使用两个char型变量来表示,这两个char型变量就组成了所谓的surrogate pair(在底层实际上是使用一个int进行表示的)。第一个char型变量的范围称为“高代理部分”(high-surrogates range,从"uD800到"uDBFF,共1024个码位), 第二个char型变量的范围称为low-surrogates range(从"uDC00到"uDFFF,共1024个码位),这样使用surrogate pair可以表示的字符数一共是1024的平方计1048576个,加上BMP的65536个码位,去掉2048个非法的码位,正好是1,112,064个码位。
关于Unicode的码空间实际上有一些稍不小心就会让人犯错的地方。比如我们都知道从U+0000到U+FFFF的部分被称为基本多语言面(Basic Multilingual Plane,BMP),这个范围内的字符在使用UTF-16编码时,只需要一个char型变量就可以保存。仔细看看这个范围,应该有65536这么大,因此你会说单字节的UTF-16编码能够表示65536个字符,你也会说Unicode的基本多语言面包含65536个字符,但是再想想刚才说过的surrogate pair,一个UTF-16表示的增补字符(再一次的,需要两个char型变量才能表示的字符)怎样才能被正确的识别为增补字符,而不是两个普通的字符呢?答案你也知道,就是通过看它的第一个char是不是在高代理范围内,第二个char是不是在低代理范围内来决定,这也意味着,高代理和低代理所占的共2048个码位(从0xD800到0xDFFF)是不能分配给其他字符的。
但这是对UTF-16这种编码方法而言,而对Unicode这样的字符集呢?在Unicode的编号中,U+D800到U+DFFF是否有字符分配?答案是也没有!这是典型的字符集为方便编码方法而做的安排(你问他们这么做的目的?当然是希望基本多语言面中的字符和一个char型的UTF-16编码的字符能够一一对应,少些麻烦,从中我们也能看出UTF-16与Unicode间很深的渊源与结合)。也就是说,无论Unicode还是UTF-16编码后的字符,在0x0000至0xFFFF这个范围内,只有63488个字符。这就好比最初的CPU被勉强拿来做多媒体应用,用得多了,CPU就不得不修正自己从硬件上对多媒体应用提供支持了。
尽管不情愿,但说到这里总还得扯扯相关的概念:代码点和代码单元。
代码点(Code Point)就是指Unicode中为字符分配的编号,一个字符只占一个代码点,例如我们说到字符“汉”,它的代码点是U+6C49。
代码单元(Code Unit)则是针对编码方法而言,它指的是编码方法中对一个字符编码以后所占的最小存储单元。例如UTF-8中,代码单元是一个字节,因为一个字符可以被编码为1个,2个或者3个4个字节;在UTF-16中,代码单元变成了两个字节(就是一个char),因为一个字符可以被编码为1个或2个char(你找不到比一个char还小的UTF-16编码的字符,嘿嘿)。说得再罗嗦一点,一个字符,仅仅对应一个代码点,但却可能有多个代码单元(即可能被编码为2个char)。
以上概念绝非学术化的绕口令,这意味着当你想以一种统一的方式指定自己使用什么字符的时候,使用代码点(即你告诉你的程序,你要用Unicode中的第几个字符)总是比使用代码单元更好(因为这样做的话你还得区分情况,有时候提供一个16进制数字,有时候要提供两个)。
例如我们有一个增补字符???(哈哈,你看到了三个问号对吧?因为我的系统显示不出这个字符),它在Unicode中的编号是U+2F81A,当在程序中需要使用这个字符的时候,就可以这样来写:
char[]chars=s.toCharArray();
for(char c:chars){
System.out.format("%x",(short)c);
}
后面的for循环把这个字符的UTF-16编码打印了出来,结果是
d87edc1a
注意到了吗?这个字符变成了两个char型变量,其中0xd87e就是高代理部分的值,0xdc1a就是低代理的值。
相关推荐
在Java编程语言中,理解和掌握字符集编码是至关重要的,特别是在处理各种文本数据时。本文主要探讨了编码字符集和字符集编码的区别,这对于软件开发人员来说是基础且必要的知识。 首先,我们要区分两个概念:编码...
香港增补字符集香港增补字符集香港增补字符集香港增补字符集[参照].pdf
Unicode编码解决了多语言环境中字符编码不统一的问题,使得各种语言的字符可以在同一环境中被正确处理。在Java中,字符串是以Unicode编码存储的,这意味着它可以无缝地处理各种语言的文本。 四、UTF UTF(Unicode ...
通过对ISO 8859-1、GB2312/GBK、Unicode和UTF等常见编码的理解,以及Java提供的字符串操作方法(如`getBytes`和`new String`),开发者可以有效地解决实际项目中的字符编码问题,确保应用程序能够正确地处理各种文本...
UTF-8(Unicode Transformation Format-8)是一种可变长度的字符编码格式,主要用于在网络中快速传输Unicode字符。UTF-8的基本原理是根据Unicode字符的范围,将其映射成不同长度的编码,具体规则如下: - 每个英文...
本文主要探讨了字符编码的历史发展,特别是ASCII、Unicode和UCS的关系及其在Java中的应用。 ASCII,即美国标准信息交换码,是最早广泛使用的字符编码标准,使用7位二进制表示128个字符,主要覆盖英文字符。随着全球...
Java中的字符编码转换是编程实践中不可或缺的一部分,尤其是在处理多语言和跨平台的场景下。Java选择了UTF-16作为其内部字符表示的标准,这确保了在JVM内存中,所有字符都以统一的方式存储,避免了编码不一致带来的...
在运行时,JVM 使用 Unicode 进行字符编码。这意味着如果要从磁盘文件、数据库或网络读取字符数据,需要正确地指定字符集编码。例如,使用 `new String(bytes, "UTF-8")` 来创建字符串对象时,必须确保传入的 `bytes...
在Java编程语言中,处理字符串时,了解字符串的编码类型是非常重要的。编码类型决定了字符集,它定义了如何将字符转换为数字(字节)以及如何将数字转换回字符。常见的编码类型有ASCII、ISO-8859-1、UTF-8、GBK等。...
这两个类位于`java.net`包下,可以帮助开发者进行字符串编码和解码,确保数据在网络传输过程中的正确性。 `URLEncoder`类提供了`encode`静态方法,用于将普通字符串编码成`application/x-www-form-urlencoded` MIME...
在Java开发中,连接Oracle数据库是一项常见的任务,尤其是在处理特定字符集如American ASCII7时,开发者需要对字符编码有深入的理解。Oracle数据库支持多种字符集,包括ASCII,它是最基础的7位字符集,包含32个控制...
### Java中的Unicode与字符集详解 #### 一、引言 在软件开发过程中,正确处理文本数据至关重要。尤其是在全球化日益加深的今天,软件不仅要能够处理英语等常见的西方语言,还要支持世界各地的语言,包括中文、日文...
在Java编程语言中,字符编码是一个至关重要的概念,它涉及到如何表示、存储和处理文本数据。字符编码系统如ASCII、ISO-8859-1、Unicode(包括UTF-8、UTF-16等)被广泛使用。本教程将深入探讨Java中的字符编码,以及...
通过以上的介绍,我们可以了解到 Java 中字符串和字符编码的处理是非常重要的,特别是在跨平台和多语言环境中。正确的字符编码管理不仅可以避免乱码问题,还能提高程序的健壮性和可维护性。希望本文能帮助开发者们更...
在 JAVA 中,中文字符编码问题一直是让人头疼的问题,特别是在 WEB 应用中。网上的分析文章和解决方案都很多,但总是针对某些特定情况的。本文将详细解释 JAVA 中文字符编码问题的根源,并提供解决方案。 一、JAVA ...
通过解析字符串获取字符串编码类型的java代码
在Java编程语言中,处理字符串是非常常见的操作,尤其是在涉及到文本分析和处理的场景。本文将深入探讨如何在Java中进行中文...在Java中处理字符串,特别是涉及到特殊字符集如中文时,对字符编码的理解是必不可少的。
在Java编程语言中,字符集编码涉及到java.nio.charset.Charset类,它为不同编码提供了编程支持。java.io.InputStreamReader类用于基于字符集的字符流输入,可以在读取文件或数据流时指定字符集,以正确显示字符内容...
Java字符集编码应用探讨
总的来说,字符集和字符编码是计算机处理文本的基础,理解它们的工作原理和相互关系有助于解决跨语言交流的问题,以及在编程中避免常见的乱码问题。随着全球化的发展,Unicode编码和与其相关的UTF家族成为了现代...