Unicode UTF-8 UTF-16
二进制,十进制和十六进制
在Java中一个字节(byte)由八位组成
对于1000 0110
转化为有符号十进制: -122
转化为无符号十进制: 134
转化为十六进制: 86
tips:
最高位为1,一般我会算低七位的值,转化为有符号-128
,转化为无符号+128
在Java里,byte -> int,int为有符号十进制
Unicode
最新的Unicode采用四个字节表示全部字符,范围为0x0 - 0x10FFFF
。十六进制转化为十进制即为codepoint值。在Java中还有个codeunit的概念。
Unicode目前实际使用的编码方式为UCS-2,一个字符占用两个字节。能够涵盖Unicode全部字符的为UCS-4,一个字符占用四个字节。
UTF-8
UTF-8为Unicode的一种实现方式,是一种变长编码。其编码规则为:
codepoint | Unicode | UTF-8 |
0 - 127 | U-0000 0000 - U-0000 007F | 0xxxxxxx |
128 - 2047 | U-0000 0080 - U-0000 07FF | 110xxxxx 10xxxxxx |
2048 - 65535 | U-0000 0800 - U-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
65536 - 1114111 | U-0001 0000 - U-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
xx
部分为codepoint二进制值依次填写,不足的位补0。
UTF-16
UTF-16是Unicode的另一种实现方式,有UTF-16 BE和UTF-15 LE两种,为了区分,在UTF-16 BE前添加FF FE
,在UTF-16 LE前添加FE FF
。在windows和linux中一般使用LE。
编码规则:
-
U+0000 - U+FFFF
:UTF-16对应的是其codepoint -
U-0001 0000 - U-0010 FFFF
:
- 码位减去
0x10000
,得到的值的范围为20比特长的0..0xFFFFF
.
高位的10比特的值(值的范围为0..0x3FF
)被加上0xD800得到第一个码元或称作高位代理(high surrogate),值的范围是0xD800..0xDBFF.由于高位代理比低位代理的值要小,所以为了避免混淆使用,Unicode标准现在称高位代理为前导代理(lead surrogates)。 - 低位的10比特的值(值的范围也是
0..0x3FF
)被加上0xDC00得到第二个码元或称作低位代理(low surrogate),现在值的范围是0xDC00..0xDFFF
.由于低位代理比高位代理的值要大,所以为了避免混淆使用,Unicode标准现在称低位代理为后尾代理(trail surrogates)。
U-0001 0000 - U-0010 FFFF
未验证,来自UTF-16
Java使用的编码方式是UTF-16
UTF-32
UTF-32差不多等于UCS-4,UTF-16差不多等于UCS-2
----------
汉字“一”
CJK Unified Ideographs,中日韩统一表意文字,范围U+4E00-U+9FFF
。“一”是其中的第一个字符,对应的Unicode为U+4E00
。
- 其UTF-8编码:因为
U+4E00
在U+0800
-U+FFFF
的范围中,所以UTF-8需要用三个字节去表示。其codepoint为19968,化为二进制为100 1110 0000 0000
,填写至1110xxxx 10xxxxxx 10xxxxxx
,为11100100 10111000 10000000
。 - 其UTF-16编码:因为
U+4E00
在U+0000
-U+FFFF
范围中,所以其UTF-16为0100 1110 0000 0000
Java中String类的getBytes()方法
1、UTF-16编码
String s = "一";
byte[] b = s.getBytes("UTF-16");
System.out.println("b.length: " + b.length);
for (int i = 0; i < b.length; i++) {
System.out.print("b[" + i + "]: " + b[i]);
}
一个汉字占用两个byte,那么很显然b.length = 2
,b[0] = 78
,b[1] = 0
,再看看编译器输出的结果:
b.length: 4
b[0]: -2
b[1]: -1
b[2]: 78
b[3]: 0
@@!和预期的不大一样。再看看-2和-1,其实它们分别是FE FF
的十进制形式,因为前面有说到UTF-16有两种编码形式BE
和LE
,而FE FF
代表的是LE
。
String s = "一丁";
byte[] b = s.getBytes("UTF-16");
System.out.println("b.length: " + b.length);
for (int i = 0; i < b.length; i++) {
System.out.println("b[" + i + "]: " + b[i]);
}
“丁”是“一”后面的字符,再看看结果:
b.length: 6
b[0]: -2
b[1]: -1
b[2]: 78
b[3]: 0
b[4]: 78
b[5]: 1
2、UTF-8
String s = "一";
byte[] b = s.getBytes("UTF-8");
System.out.println("b.length: " + b.length);
for (int i = 0; i < b.length; i++) {
system.out.println("b[" + i + "]: " + b[i]);
}
“一”在UTF-8中占用三个字节
b.length: 3
b[0]: -28
b[1]: -72
b[2]: -128
其中-28
是11100100
的有符号十进制形式,-72
为10111000
,-128
为10000000
参考:
http://www.cnblogs.com/kingcat/archive/2012/10/16/2726334.html
https://zh.wikipedia.org/wiki/Unicode
2015/12/4 17:13:16