在程式設計過程中,字元的編碼問題不可避免。以Web應用為例,HTTP協定中封包頭裡的Accept-Charset、Accept-Encoding、Content-Encoding等就是字元編碼的一種展現。當我們充分了解字元編碼的原理後,我們就可以避免在看到諸如
??OY}T??N*NuL?
亂碼的情況。
基本概念
編碼:把一種資訊格式轉換為另一種資訊格式。對與計算機而言,此過程是把我們自然世界裡的字元、聲頻、音頻等轉換為二進制形式。
解碼:編碼的逆過程。
亂碼:不能正确顯示字元的現象,原因多是編碼與解碼所用的映射關系不比對。
字元集:某一系統所有字元的集合。如:中文字元集包括漢字、漢字元号等。
字元編碼:把字元集中的字元編碼成指定集合中的對象。如Unicode編碼、GB2312字元編碼。通常,人們認為字元集和字元編碼是同義詞(因為特定的字元編碼會有唯一的字元集與之對應)。
各國編碼
了解了編碼的基本概念之後,我們需要明确一下,各國是如何對本國字元進行編碼的:
ASCII編碼
由于計算機是西方國家産物。是以,在計算機被發明的很長時間内,都是使用一種叫ASCII碼的東西對西方國家常用的字元進行編碼。
ASCII使用一個位元組存儲字元,且第一位同一為0,實際隻能表示128個字元。對應的碼表可以在這個網站檢視。
各國獨立編碼
雖然ASCII對于美國等西方國家使用時勉強足夠,但是對非英語系的國家而言,其字元遠遠不知128個,是以,各國紛紛拟定能夠容納本國字元的編碼。比方中國的GB2312編碼、日本的ISO2022編碼。
Unicode編碼
各國使用各自的編碼,在本國使用當然不會有問題。如果編碼的對象需要在網際網路上傳輸、共享,還是會有亂碼的發生。是以,一個懷着「把世界上所有的字元都用同一編碼」偉大夢想的,統一碼聯盟誕生了。這個聯盟拟定的編碼方式如:UTF-32(使用4個位元組存儲一個字元);UTF-16(使用2個位元組存儲一個字元);UTF-8(使用1-4個位元組變長編碼)等實作。
UTF-8編碼
我們知道UTF-8編碼隻是Unicode編碼的一種實作,但在程式設計中,UTF-8也是最經常使用的。是以,這裡簡單介紹一下UTF-8的編碼政策。
對于UTF-8編碼的字元,第一個位元組裡的高x位1表示該字元用x位位元組編碼;接下來的x位前兩位必是10。下面的表格簡單模拟了UTF-8編碼過程:
碼點位數 | 碼點起值 | 碼點終值 | 位元組序列 | Byte1 | Byte2 | Byte3 | Byte4 | Byte5 | Byte6 |
---|---|---|---|---|---|---|---|---|---|
7 | U+0000 | U+007F | 1 | 0xxxxxxx | NULL | NULL | NULL | NULL | NULL |
11 | U+0080 | U+07FF | 2 | 110xxxxx | 10xxxxxx | NULL | NULL | NULL | NULL |
16 | U+0080 | U+FFFF | 3 | 1110xxxx | 10xxxxxx | 10xxxxxx | NULL | NULL | NULL |
21 | U+10000 | U+1FFFFF | 4 | 11110xxx | 10xxxxx | 10xxxxxx | 10xxxxxx | NULL | NULL |
26 | U+200000 | U+3FFFFFF | 5 | 111110xx | 10xxxxxx | 10xxxxxx | 10xxxxxx | 10xxxxxx | NULL |
31 | U+4000000 | U+7FFFFFFF | 6 | 1111110x | 10xxxxxx | 10xxxxxx | 10xxxxxx | 10xxxxxx | 10xxxxxx |
由上面的表格可以看出,當高1位為0時,UTF-8編碼和ASCII編碼一緻。
編碼應用
在JEE開發過程中,假定有如下JSP頁面:
<%@ page pageEncoding="UTF-8" contentType="text/html;charset=UTF-8"%>
<%
out.print("中國");
%>
在這裡:
- pageEncoding:JSP轉換成Servlet時使用的編碼
- contentType:擷取printWriter時,使用的編碼
兩者使用的映射一樣,不會出現亂碼。
參考文獻
維基百科|字元編碼
維基百科|UTF-8