Java字符相关知识
以Q&A的方式总结Java字符相关知识
字符编码基本概念:
Q: 什么是字符?
A: 字符(character )是抽象的最小文本单位。它没有固定的形状(可能是一个字形),而且没有值。“A”是一个字符,“严”是一个字符,“€”(德国、法国和许多其他欧洲国家通用货币的标志)也是一个字符。
Q: 什么是字符集?
A: 字符集(character set)是字符的集合。例如,汉字字符是中国人最先发明的字符,在中文、日文、韩文和越南文的书写中使用。
Q:什么是编码字符集?
A:编码字符集(coded characterset)是一个字符集,它为每一个字符分配一个唯一数字。Unicode 标准的核心是一个编码字符集,字母“A”的编码为 004116 和字符“€”的编码为 20AC16。Unicode 标准始终使用十六进制数字,而且在书写时在前面加上前缀“U+”,所以“A”的编码书写为“U+0041”。
Q: 什么是代码点?
A: 代码点(Code points)是指可用于编码字符集的数字。编码字符集定义一个有效的代码点范围,但是并不一定将字符分配给所有这些代码点。有效的 Unicode 代码点范围是 U+0000 至 U+10FFFF。Unicode 4.0 将字符分配给一百多万个代码点中的 96,382 代码点。
比如 unicode U+20C30 的代码点为134192,U+20C30和134192是等价的。在java中可通过int i =Integer.parseInt("20C30", 16);得到其代码点。
Q: 什么是增补字符?
A: 增补字符(Supplementarycharacters)是代码点在 U+10000 至 U+10FFFF 范围之间的字符,也就是那些使用原始的 Unicode 的 16 位设计无法表示的字符。从 U+0000 至 U+FFFF 之间的字符集有时候被称为基本多语言面 (BMP)。因此,每一个 Unicode 字符要么属于 BMP,要么属于增补字符。
Q: 什么是字符编码方案?
A: 字符编码方案(character encodingscheme)是从一个或多个编码字符集到一个或多个固定宽度代码单元序列的映射。最常用的代码单元是字节,但是 16 位或 32 位整数也可用于内部处理。UTF-32、UTF-16 和 UTF-8 是 Unicode 标准的编码字符集的字符编码方案。
Q: UTF-32、UTF-16 、UTF-8 都是什么意思?
A: 这些都是unicode的编码方式,说白了就是如何用二进制来表示unicode。
UTF-32 即将每一个 Unicode 代码点表示为相同值的 32 位整数。很明显,它是内部处理最方便的表达方式,但是,如果作为一般字符串表达方式,则要消耗更多的内存。
UTF-16 使用一个或两个未分配的 16 位代码单元的序列对 Unicode 代码点进行编码。值 U+0000 至U+FFFF 编码为一个相同值的 16位单元。增补字符编码为两个代码单元,第一个单元来自于高代理范围(U+D800 至U+DBFF),第二个单元来自于低代理范围(U+DC00至 U+DFFF)。这在概念上可能看起来类似于多字节编码,但是其中有一个重要区别:值U+D800 至 U+DFFF 保留用于 UTF-16;没有这些值分配字符作为代码点。这意味着,对于一个字符串中的每个单独的代码单元,软件可以识别是否该代码单元表示某个单单元字符,或者是否该代码单元是某个双单元字符的第一个或第二单元。这相当于某些传统的多字节字符编码来说是一个显著的改进,在传统的多字节字符编码中,字节值 0x41 既可能表示字母“A”,也可能是一个双字节字符的第二个字节。
UTF-8 使用一至四个字节的序列对编码 Unicode 代码点进行编码。U+0000 至U+007F 使用一个字节编码,U+0080至 U+07FF 使用两个字节,U+0800 至 U+FFFF使用三个字节,而U+10000 至 U+10FFFF 使用四个字节。UTF-8 设计原理为:字节值 0x00 至0x7F 始终表示代码点U+0000 至 U+007F(Basic Latin 字符子集,它对应 ASCII 字符集)。这些字节值永远不会表示其他代码点,这一特性使 UTF-8 可以很方便地在软件中将特殊的含义赋予某些 ASCII 字符。
Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
下表所示为几个字符不同表达方式的比较:
Unicode 代码点 |
U+0041 |
U+00DF |
U+6771 |
U+10400 |
||||||||||
表示字形 |
|
|
|
|
||||||||||
UTF-32 代码单元 |
|
|
|
|
||||||||||
UTF-16 代码单元 |
|
|
|
|
||||||||||
UTF-8 代码单元 |
|
|
|
|
Java字符基本概念
Q: Java 使用什么字符集,能支持多少字符?
A: Java使用Unicode编码,unicode可支持超过100万个字符,目前使用10万个左右。
Q: Java char与unicode有啥关系?
A: Java char类型为16bit,支持的字符为0x0-0xffff, 即0- 65535共 65536个字符。
java刚开始用char来表示unicode,由于刚开始unicode最多使用16bit表示。因此char能够表示全部的unicode字符。
后来由于unicode 4.0 规定unicode支持的字符远远超过65536个字符。因此char现在不能表示所有的unicode字符。
仅仅能表示0x0-0xffff之间的字符。而oxffff以上的字符称为增补字符。
Q: 在java中,超过char范围的增补字符如何显示?
A: 使用代码点(codepoint)来表示,用一个int类型的整数来表示unicode中的代码点。
比如:u+20C30 超出了0xffff,则可通过以下代码:
int i = Integer.parseInt("20C30", 16);
char[]chs = Character.toChars(i);
Stringstr = new String(chs);
byte[]bs = str.getBytes();
Stringhex = StringHelper.hex(bs); // StringHelper.hex()是将字节数组转化为16进制字符串,上网搜一下实现方式即可。
System.out.println(i+ " " + Arrays.toString(bs) + " " + hex + " " +str + " " + Arrays.toString(chs));
输出结果:134192[-16, -96, -80, -80] f0a0b0b0 𠰰 [?, ?]
其中:
134192 : u+20C30的代码点
[-16, -96, -80, -80] : u+20C30 UTF-8表示的字节序列, 我机器是utf-8环境。
f0a0b0b0 : u+20C30的16进制字符串
𠰰: u+20C30表示的字符
[?, ?] : 当将unicode分成两个Java字符表示时,UTF-8中找不到对应的unicode字符。
Q: 在java中,超过char范围的增补字符如何显示?
A: 使用代码点(codepoint)来表示,用一个int类型的整数来表示unicode中的代码点。
未完待续........
参考文章:
Java 平台中的增补字符 : http://java.sun.com/developer/technicalArticles/Intl/Supplementary/index_zh_CN.html
字符编码笔记:ASCII,Unicode和UTF-8 :http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
posted on 2010-12-29 22:06 NanguoCoffee 阅读(1264) 评论(0) 编辑 收藏 举报