http://blog.csdn.net/zhangxiaoxiang/archive/2006/08/22/1106714.aspx

問題:
public class TestUTF8
{
?? public static void main(String [] args) throws Exception
?? {
????? ?byte[] bytes = {(byte)0xC0,(byte)0xB1};
?????? String str = new String(bytes,"UTF-8");
?????? System.out.println(str.getBytes("UTF-8").length);
?? }
}

程序運行后打印的結果如下:
1

這個程序將 兩個 字節的bytes數組按UTF-8編碼轉換成字符串,再將結果字符串轉換成UTF-8編碼的字節數組,打印出的這個字節數組的長度為?1 。為什么兩個字節的數組轉換成的字符串反轉回去的字節數組的長度卻為一呢??

答案:
這個問題應該是由UTF-8編碼的特點造成的。
UTF-8是一種變長字節編碼方式。對于某一個字符的UTF-8編碼,如果只有一個字節則其最高二進制位為0;如果是多字節,其第一個字節從最高位開始,連續的二進制位值為1的個數決定了其編碼的位數,其余各字節均以10開頭。UTF-8最多可用到6個字節。
如表:
1字節 0xxxxxxx
2字節 110xxxxx 10xxxxxx
3字節 1110xxxx 10xxxxxx 10xxxxxx
4字節 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
5字節 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
6字節 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
因此UTF-8中可以用來表示字符編碼的實際位數最多有31位,即上表中x所表示的位。除去那些控制位(每字節開頭的10等),這些x表示的位與UNICODE編碼是一一對應的,位高低順序也相同。
實際將UNICODE轉換為UTF-8編碼時應先去除高位0,然后根據所剩編碼的位數決定所需最小的UTF-8編碼位數。
因此那些基本ASCII字符集中的字符(UNICODE兼容ASCII)只需要一個字節的UTF-8編碼(7個二進制位)便可以表示。

對于上面的問題,代碼中給出的兩個字節是
十六進制:C0 B1
二進制:11000000 10110001
對比兩個字節編碼的表示方式:
110xxxxx 10xxxxxx
提取出對應的UNICODE編碼:
00000 110001
可以看出此編碼并非“標準”的UTF-8編碼,因為其第一個字節的“有效編碼”全為0,去除高位0后的編碼僅有6位。由前面所述,此字符僅用一個字節的UTF-8編碼表示就夠了。
JAVA在把字符還原為UTF-8編碼時,是按照“標準”的方式處理的,因此我們得到的是僅有1個字節的編碼。

大家可以試試運行這段代碼:
public class TestUTF8 {
public static void main(String[] args) throws Exception {
byte[][] bytes = {
// 00110001
{(byte)0x31},
// 11000000 10110001
{(byte)0xC0,(byte)0xB1},
// 11100000 10000000 10110001
{(byte)0xE0,(byte)0x80,(byte)0xB1},
// 11110000 10000000 10000000 10110001
{(byte)0xF0,(byte)0x80,(byte)0x80,(byte)0xB1},
// 11111000 10000000 10000000 10000000 10110001
{(byte)0xF8,(byte)0x80,(byte)0x80,(byte)0x80,(byte)0xB1},
// 11111100 10000000 10000000 10000000 10000000 10110001
{(byte)0xFC,(byte)0x80,(byte)0x80,(byte)0x80,(byte)0x80,(byte)0xB1},
};
for (int i = 0; i < 6; i++) {
String str = new String(bytes[i], "UTF-8");
System.out.println("原數組長度:" + bytes[i].length +
"\t轉換為字符串:" + str +
"\t轉回后數組長度:" + str.getBytes("UTF-8").length);
}
}
}
運行結果為:
原數組長度:1 轉換為字符串:1 轉回后數組長度:1
原數組長度:2 轉換為字符串:1 轉回后數組長度:1
原數組長度:3 轉換為字符串:1 轉回后數組長度:1
原數組長度:4 轉換為字符串:1 轉回后數組長度:1
原數組長度:5 轉換為字符串:1 轉回后數組長度:1
原數組長度:6 轉換為字符串:1 轉回后數組長度:1


唉~~,看來我得加強字符編碼方面的知識了!