http://www.csdn1 2 3.com/html/itweb/20130730/29422_29378_29408.htmjavascript
******************************css
1、字符集與文字編碼簡介 html
1. 計算機如何顯示文字java
咱們知道,計算機是以二進制的「形式」來保存和處理數據的,也 就是說,無論咱們使用鍵盤進行輸入,仍是讓計算機去讀取一個文本文件,計算機獲得的原始內容是一些二進制序列,當須要對這些二進制序列進行顯示時,計算機 會依照某種「翻譯機制」(也就是編碼方式),取到這些二進制序列所表示的每一個文字的「輪廓描述」(點陣或者矢量圖),知道了輪廓,計算機即可以將二進制序 列所表示的實際的文字形狀顯示到屏幕上了,這裏面的思想和用學號來表示一個學生是同樣的。(固然,這裏面具體的知識點會不少,相關知識能夠參考《計算機圖 形學》中顯示原理的部分和其餘與計算機顯示原理相關的基礎書籍)。web
2. 字符集算法
將一些天然語言中的字符組成一個集合,並對集合中的每一個字符制 定規範化的編碼方式,這個字符的集合和規範化的編碼方式就組成了一個字符集。如ASCII字符集裏面包括了全部的英文字母,而且指定了這些英文字母的編碼 規則。GB2312字符集裏面包括了經常使用的簡體漢字,而且指定了這些簡體漢字的編碼規則。chrome
3. 字符編碼編程
字符編碼,就是創建一套天然語言中的「字符」跟計算機可以存儲 處理的二進制數的映射的規則,即在一個字符集內,用一個特定的二進制數表示一個惟一「字符」,相似於學號跟學生的映射關係。爲了保證統一性,兼容性,國際 上會對「字符」和「內碼」的映射關係指定標準,這樣就有了ASCII、Unicode等標準的編碼方式,詳細的編碼方式請參考字符編碼和其餘相關資料。瀏覽器
2、泛意義上的編碼和解碼服務器
1. 爲何須要編碼
當數據不利於處理、存儲的時候,就須要對它們進行編碼。如對字符進行編碼是由於天然語言中的字符不利於計算機處理和存儲。對圖片信息、視頻信息、聲音信息進行壓縮、優化,將其「格式化」,是爲了在保證媒體資源質量的同時,儘可能的節省網絡帶寬和本地存儲的空間。對URL進行編碼,是爲了不URL解析發生歧義,簡化解碼方式,如:URL採用「&」做爲不一樣參數的分隔符,假如某個特定的參數的名稱或者值自己就包括分隔符「&」,若是不將參數中的「&」作編碼轉換,那勢必會增長URL解析的複雜性,提升解析錯誤的機率。
2. 怎麼樣進行編碼和解碼
根據實際需求的差別,編碼、解碼算法有可能會很複雜,也有可能很是的簡單,可是從根本上來說,編碼、解碼只是在作翻譯工做,將一種形式的數據翻譯爲另外一種形式的數據,如,最簡單的編碼、解碼就是至關於從一個Map中根據key查找value,而後使用value代替實際數據中的key的值。複雜一點兒的編碼如javascript中的encodeURIComponent和decodeURIComponent,encodeURIComponent負責將字符串中不符合URL編碼規範的字符轉換爲「%」形式的十六進制Unicode內碼序列,decodeURIComponent負責將「%」形式的十六進制Unicode內碼序列轉換爲實際的字符。
3、HTTP協議中的編碼和解碼
1. URL的編碼和解碼
首先,因爲URL是採用ASCII字符集進行編碼的,因此若是URL中含有非ASCII字符集中的字符,那就須要對其進行編碼。再者,因爲URL中好多字符是保留字,他們在URL中具備特殊的含義。如「&」表示參數分隔符,若是想要在URL中使用這些保留字,那就得對他們進行編碼。
根據2005年發佈的RFC3986「%編碼」規範:對URL中屬於ASCII字符集的非保留字不作編碼;對URL中的保留字須要取其ASCII內碼,而後加上「%」前綴將該字符進行替換(編碼);對於URL中的非ASCII字符須要取其Unicode內碼,而後加上「%」前綴將該字符進行替換(編碼)。因爲這種編碼是採用「%」加上字符內碼的方式,因此,有些地方也稱其爲「百分號編碼」。
雖然「百分號編碼」對URL的編碼方式作了詳細的規定,可是實踐中,瀏覽器對於URL的編碼方式仍是存在一些差別(主要表如今對非ASCII字符編碼的差別),接下來咱們首先展現不一樣瀏覽器(chrome和IE)對URL編碼
的差別性,而後再對這些差別性作一些客觀的總結和分析。
1) 對URL中的非ASCII字符的編碼,原始URL地址:http://test/wangfengpaopao/王豐,請求方式爲直接在瀏覽器地址欄輸入地址,發起請求。
a) chrome
b) IE
能夠看出對於路徑中的非ASCII字符,chrome和IE都是按照RFC3986「%編碼」進行編碼的,取的是非ASCII字符的Unicode內碼。
2) 對URL參數中的非ASCII字符的編碼,原始URL地址:http://test/wangfengpaopao/王豐?name=王豐,請求方式爲直接在瀏覽器地址欄輸入地址,發起請求。
a) chrome和IE11
b) IE11如下版本(使用gbk進行解碼)
能夠看出對於查詢參數中的非ASCII字符,chrome及其IE11都是按照都是按照RFC3986「%編碼」進行編碼的,取的是非ASCII字符的Unicode內碼。IE11如下版本直接發送的是非ASCII字符相對應的當前系統默認編碼的內碼。
3) 對錶單字段name的值中的非ASCII字符的編碼,請求地址:http://test/wangfengpaopao/王豐,請求方式爲get。
a) Chrome
i. 頁面gbk編碼
ii. 頁面utf-8編碼
b) IE
i. 頁面gbk編碼
ii. 頁面utf-8編碼
能夠看出當經過表單發送get請求時,對於表單字段內容中的非ASCII,chrome和IE都會採用當前頁面的編碼對其進行「百分號」編碼。
4) 對錶單字段name的值中的非ASCII字符的編碼,請求地址:http://test/wangfengpaopao/王豐,請求方式爲post,enctype爲application/x-www-form-urlencoded。
a) chrome
i. 頁面UTF-8編碼
ii. 頁面GBK編碼
b) IE
i. 頁面UTF-8編碼
ii. 頁面GBK編碼
能夠看出當經過表單發送post請求時,對於表單字段內容中的非ASCII,chrome和IE都會採用當前頁面的編碼對其進行「百分號」編碼。
5) 對URL中的非ASCII字符的編碼,原始URL地址:http://test/wangfengpaopao/王豐?name=王豐,請求方式爲發起AJAX請求,method爲get。
a) Chrome
i. 頁面utf-8編碼
ii. 頁面gbk編碼
b) IE
i. 頁面utf-8編碼
1. IE6(gbk解碼)
2. IE11
ii. 頁面GBK編碼
1. IE6(gbk解碼)
2. IE11
能夠看出,對於URL中的非ASCII字符,ie6沒有作任何的編碼工做,而chrome和IE11則是按照用表單get請求的方式對URL進行編碼的。
6) 對URL中的非ASCII字符的編碼,原始URL地址:http://test/wangfengpaopao/王豐,請求方式爲發起AJAX請求,method爲post,數據位name=王豐,content-type爲application/x-www-form-urlencoded。
a) Chrome
i. 頁面utf-8編碼
ii. 頁面gbk編碼
b) IE
i. 頁面utf-8編碼
1. IE6
2. IE11
ii. 頁面GBK編碼
1. IE6
2. IE11
能夠看出,對於使用post發送而且content-type爲application/x-www-form-urlencoded的請求,各個瀏覽器都沒有對數據進行「百分號」編碼。
從上面的實驗結果咱們看得出:
① 對於URL中的路徑部分,IE和chrome都會統一採用utf-8編碼對URL中的非ASCII字符進行百分號編碼。
② 對於新開頁面,IE11如下版本不會對URL中的參數部分作編碼,chrome和IE11會採用utf-8編碼對URL中的非ASCII字符進行百分號編碼。
③ 對於經過表單發起的請求(不論是post仍是get方式),IE和chrome都會採用當前頁面的默認編碼對URL參數中的非ASCII字符進行百分號編碼。
④ 對於AJAX經過get方式發起的請求,IE11和chrome會根據當前頁面的默認編碼對URL參數中的非ASCII字符進行百分號編碼。而IE6不會對URL非ASCII表示的路徑信息和參數信息進行編碼。
⑤ 對於AJAX經過post方式發起的請求,即使設定了application/x-www-form-urlencoded頭信息,瀏覽器也不會對數據作任何的編碼(或者說瀏覽器不把發送的數據當作URL的一部分)。
不一樣的瀏覽器在不一樣狀況下處理URL中非ASCII字符的編碼方式可謂是千差萬別,好在瀏覽器對錶單數據的編碼處理是一致的,即:對URL路徑中的非ASCII字符采用UTF-8字符集進行百分號編碼;對中的表單數據(包括post時enctype爲application/x-www-form-urlencoded),採用頁面默認的編碼字符集進行百分號編碼。
對於AJAX發起請求時URL編碼的差別性,咱們能夠對URL或者數據中的非ASCII字符使用javascript的encodeURIComponent進行編碼,統一編碼方式,簡化服務器解碼的複雜度。
2. 瀏覽器對不一樣媒體資源類型(mime-type)的「資源」的解碼
1) 與資源類型和編碼類型相關的HTTP頭信息。
a) 瀏覽器request時攜帶的頭信息
b) 服務器response時攜帶的頭信息
當經過瀏覽器發起一個資源請求,瀏覽器會攜帶Accept頭信息,標識瀏覽器須要的mime-type,而且指定瀏覽器對不一樣mime-type的喜愛係數q,同時瀏覽器也會發送Accept-Charset頭信息,標識瀏覽器字符集解碼類型。
當服務器返回「符合」瀏覽器需求的資源時,服務器也會攜帶Content-Type頭信息,標識返回資源的媒體類型和編碼方式。
2) 瀏覽器對不一樣媒體資源類型的資源的解析過程
無論怎樣,瀏覽器發起一個請求時所攜帶的mime-type信息只是對服務器返回資源的一種「指望」,資源自己的mime-type還得用服務器應答時攜帶的mime-type信息進行表示。
籠統的講,對於文本類型的數據(html/css/js/xml等),瀏覽器首先會根據資源的Charset,將文本流的編碼轉換爲與資源的mime-type相對應的解碼器處理數據時所使用的編碼,好比對於javascript文件,若是文本流自己 是GBK編碼的,那就得首先轉爲Unicode編碼,而後再交給javascript引擎去解析執行。固然對於不一樣類型的資源,瀏覽器進行解碼的流程也是不同的,下面會用流程圖較詳細的說明下瀏覽器對於HTML、CSS、Javascript的通用的解碼步驟。
① 瀏覽器對於HTML文檔的解碼流程
② 瀏覽器對於CSS/JS文檔的解碼流程
3) AJAX請求中,瀏覽器對「數據」的解碼流程
AJAX請求跟頁面內的有資源屬性source的標籤發起的請求有所不一樣,從本質來講,AJAX請求獲得的數據,瀏覽器都認爲它是普通的文本流,跟具體的mime-type無關,即使是responseXML這樣的數據,它也是由瀏覽器對responseText進行了XML解析,這與使用javascript對responseText進行XML解析的道理是同樣的。
AJAX解碼的流程
3. 服務器對資源的編碼和解碼
弄清了編碼和解碼的原理以及瀏覽器的編解碼流程,服務器的編碼和解碼可說的已經很少了,未來兵擋,水來土掩而已。要說的是爲了不URL解碼時的各類兼容性問題,最好有統一的規範,好比經過接口提交的數據中的非ASCII字符都是用encodeURIComponent進行URL編碼。爲了不瀏覽器對資源進行解碼的兼容性,服務器返回資源時,明確正確的指定Charset信息也是很重要的。
除了熟練使用本身所擅長的編程語言以及相對應的框架提供的編解碼相關的方法外,能夠參考iconv瞭解具體的編碼轉換原理,參考UCharsetDetector瞭解字符集探測原理。