字符编码
2020-04-07 本文已影响0人
userheng
Unicode字符集
在unicode出现之前,有很多编码标准,如:
编码标准 | |
---|---|
英语语系 | ASCII (7个bit表示一个字符) |
西欧 | ISO 8859-1 (8个bit表示一个字符) |
中国 | GBK |
多种编码标准产生了以下问题:
- 某个字符可能不在某个编码标准中。
- 某个字符在不同的编码标准中,其编码值不同。
Unicode字符集中包含了全球所有的通用字符,每个字符都有一个编码值,但并没有指明该字符如何在计算机中存储。
Unicode主要使不同编码标准之间的相互转换成为可能。
Unicode字符集的实现
几个专业术语的介绍:
- 码点值:字符的unicode编码值
- 码点单元:编码一个字符所需的基本单位,如UTF-16一个码点单元占16位即2字节。
UTF-16
UTF-16编码是Unicode字符集其中的一种实现,字符Unicode值到UTF-16编码值的转换示例如下:
字符 | Unicode值(16进制) | UTF-16编码值(字节之间的值以逗号分隔) |
---|---|---|
A | 0x0041 | 0,65 |
衡 | 0x8861 | -120,97 |
Java char类型与UTF-16
Java语言采用的是UTF-16编码标准,一个char占两个字节,恰好与UTF-16的一个码点单元所占大小相同。
一个码点单元16位,其值范围0~65535。可以容纳65535个字符,但后来又扩充了大量的新增字符(如中文、韩文、日文的表意字符)。一个char自然就无法表示这些字符了,至少需要一对char来表示。
如字符:"𝕆",其码点值(Unicode编码值)为:\u1d546。需要\ud835和\udd46两个码点单元来表示。
/*
* 两个char才能表示该字符,故只能用字符串引用。即 new String(new char[] {'\ud835','\udd46'})
*/
String cc = "𝕆";
System.out.println("cc的码点单元:" + cc.length() + "个");// 2
// cc是一个字符,码点值(Unicode编码值)自然是1
System.out.println("cc的码点值有" + cc.codePointCount(0, cc.length()) + "个");// 1
int codePonitValue = cc.codePointAt(0);
System.out.printf("cc的码点值%d, 十六进制为%x", codePonitValue, codePonitValue);// 120134 1d546
System.out.println("");
byte[] bytes = cc.getBytes("UTF-16");
for (byte b : bytes) {
System.out.print(b+",");//-2,-1,-40,53,-35,70,
}
System.out.println("");
//-2,-1应该是UTF-16的前缀标志
System.out.println(new String(new byte[] {-40,53,-35,70}, "UTF-16"));//𝕆
程序输出:
cc的码点单元:2个
cc的码点值有1个
cc的码点值120134, 十六进制为1d546
-2,-1,-40,53,-35,70,
𝕆