對於編碼解碼的計算過程一直沒有去研究過。以前也看了大神寫的編碼解碼的文章,當時看了似懂非懂,沒有仔細去品味,沒去實踐。正應了那句老話:紙上得來終覺淺,絕知此事要躬行。
爲什麼有編碼和解碼?二什麼時候會出現編碼和解碼?編碼解碼的算法是怎樣的?
推薦兩篇文章
http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/
http://blog.csdn.net/baixiaoshi/article/details/40786503
已經回答的很好了,^^偷懶不寫了。
基礎知識:
unicode轉換爲utf-8編碼的規則
Unicode UTF-8
0000-007F 0xxxxxxx
0080-07FF 110xxxxx 10xxxxxx
0800-FFFF 1110xxxx 10xxxxxx 10xxxxxx
如果字符對應編碼值小於0x7F,則轉換該爲1個byte,最高位爲0(0x7F轉換爲二進制爲111111,7個1。不會出現最高位爲1,最高位爲1肯定大於7F。),該字符對應的二進制替換X,不足7位前面高位加0
編碼值在0080到07FF字符,會轉換爲2個字節,並且第一個字節以110開頭,第二個字節以10開頭,字符對應的編碼值轉換爲2進制後的數據,填充X。不足位數的高位加0
編碼值在0800到FFFF字符,會轉換爲3個字節,並且第一個字節以1110開頭,後面字節以10開頭,字符對應的編碼值轉換爲2進制後的數據,填充X。不足位數的高位加0
也就是說大於07XX編碼值的字符,轉換爲字節時,第一個字節中連續1的個數表示該字符對應字節的長度
計算過程
[java] view plain copy
- String name = "中";
- char[] chars = name.toCharArray();
- //使用utf-8編碼字符集
- Charset charset = Charset.forName("utf-8");
- CharBuffer charBuffer = CharBuffer.allocate(chars.length);
- charBuffer.put(chars);
- charBuffer.flip();
- //字符編碼爲字節數組
- ByteBuffer byteBuffer = charset.encode(charBuffer);
- byte[] charToBytes = byteBuffer.array();
- System.out.println("chars.length:" + chars.length+";bytes.length:" + charToBytes.length);
- byte[] bytes = name.getBytes("utf-8");
運行後byte數組值,可通過debug查看
轉換過程
“中”的unicode通過查unicode編碼表可知爲:4E2D(十六進制的數,附件是網上找的一個編碼表),通過轉換爲二進制:100111000101101。4E2D落在了0800~ FFFF區間內,再依據前面轉換規則填充x。
填充過程:
最後獲得 11100100 10111000 10101101。
二進制到byte的換算過程
根據1個字節佔8位,換算爲字節數組[224,184,173],這和程序運行結果[-28,-72,-83],對不上,腦袋當時就卡了。然後一想不對呀,java中byte的範圍是-128到127,手工算出來的是224,184,173這明顯超出了byte數值的範圍。又一想這都是按無符號數進行二進制轉換爲byte。查了下無符號數轉換爲有符號數的規則(也有說這是補碼):最高位用來表示符號,其餘按位取反再加1。
按位取反 加1
11100100--------------->10011011-------------> 10011100
最高位爲符號位不參與計算,剩下的二進制0011100轉換爲十進制爲 28,加上符號爲-28
同理
10111000轉換後的十進制爲 :-72
10101101轉換後的十進制爲:-83
最終和程序運行結果一樣。