前言:php
一直對ANSI、UNICODE、UTF-8,GBK等概念模糊,今天翻閱了網上相關的文章(數十篇),質量參差不齊,甚至有些做者對於其中的概念也有所混淆。因此今天就作個筆記,寫個清晰簡單的文章,說明箇中關係。也怕本身忘記了,再回來看看。html
計算機篇:程序員
首先要知道兩個單位,一個是Bit(位),一個是Byte(字節)。前者是的信息元,後者是信息存儲的基本單位,8個位組成一個字節。數據庫
ASCII碼是用來對字符、數字、英文進行編碼,採用10進制,且每一個字符佔一個字節。而GBK的出現擴充了ASCII,使其能用兩位字符表示中文漢字和日文假名。其中GB2312是專門爲簡體漢字編碼的。GBK和GB2312只是兩個例子,這種擴充ASCII使用兩個字節表示一箇中文字符的方法統稱爲ANSI標準。編程
而UNICODE之因此後來出現,是爲了統一國際標準。UNICODE編碼中,每一個字符(不論中英文或符號)都是用兩個字節來表示。爲了解決UNICODE浪費存儲空間和傳輸存在的缺點,基於UNICODE標準衍生出了UTF-8編碼。UTF-8就是如今使用最普遍的國際編碼標準。瀏覽器
Web篇:安全
可能你們都有這樣的經驗,當使用FireFox瀏覽器時,在地址欄輸入某一個帶中文參數的網站時,瀏覽器會自動將參數轉化爲帶%號的格式,好比將「測試」二字轉化爲爲爲%B2%E2%CA%D4。這樣作是爲了統一URL標準以及避免一些安全問題,於此同時,瀏覽器會將URL中不可控的特殊字符也轉化爲這種格式,俗稱轉化爲URL格式,這樣的編碼方式叫作URL-encode。函數
因爲GB2312中,中文字符的表示方式爲兩個字節,一個字節8個位,而一位16進制數使用4個位。這樣一算,一箇中文字符使用4個16進制數,也就是2個2位16進制數,因此上面的例子中將「測試」轉化爲%B2%E2%CA%D4說明是轉爲GB2312格式而非UTF-8格式了。由於UTF-8中,一箇中文字符用2~4個字節表示(大多數是3個字節)。這時候問題就來了,若是該網站頁面設置使用UTF-8編碼方式,如使用了HTML的<meta>標籤:測試
<META http-equiv="content-type" content="text/html; charset=utf-8">
或者PHP的header函數:網站
<?php header("content-type:text/html; charset=utf-8"); ?>
瀏覽器傳輸時將URL參數的中文轉爲GB2312格式,而解析的時候參考了了Header或者頁面中的meta標籤將內容按解碼UTF-8格式來解碼,就顯示錯誤了。(這裏header優先級高於meta,因此二者不一致的話參考header)
下面的表格說明了經常使用瀏覽器的預約轉化方法:
直接在地址欄輸入URL
瀏覽器 | path部分 | query部分 | ||
編碼種類 | 百分比編碼 | 編碼種類 | 百分比編碼 | |
IE | UTF-8 | 是 | GB2312 | 否 |
Firefox Opera | UTF-8 | 是 | GB2312 | 是 |
Chrome Safari | UTF-8 | 是 | UTF-8 | 是 |
如何解決:
咱們先來假設一下這個問題出現的場景:訪問者直接用瀏覽器訪問帶中文參數的網站。這樣的場景雖然很少,可是終究是沒法避免的,假設你的朋友在QQ上發給你一個百度的搜索結果(「中文關鍵字」),這樣一定會出現直接訪問帶中文參數的URL的情景,而後結果是出現了亂碼。可是經我測試,如今百度已經解決了這個問題。
首先,客戶端(瀏覽器)是能夠更改預約轉化的字符集的,但咱們應該從一個程序員的角度來解決這個問題,不是讓訪問者本身經過調整客戶端來適應網頁的編碼。並且咱們得知道一點:若是在一個頁面經過腳本或者超連接的形式訪問這樣一個帶中文參數的URL的話,全部瀏覽器在query部分的編碼統一使用當前頁面的編碼方式。
要解決問題,步驟①經過refer頭判斷是不是直接從地址欄訪問的
②若是知足①,則經過User-Agent判斷瀏覽器
③根據上面的表格作編碼轉化(好比PHP的mb_convert_encoding函數)
關於其餘:
網頁編程中會遇到其餘的編碼亂碼問題,其實只要解決了以前說的那個問題(最蛋疼的問題),其餘的問題只要保證「文件存儲編碼方法-html頁面編碼方法-header編碼方法-數據庫編碼方法」四者一致便可。若是同一個網站的不一樣頁面使用不一樣的編碼方式的話,那麼在連接跳轉的使用使用JavaScript的ESCAPE函數(舉個例子)轉化而不經過瀏覽器就好了。
還有一個問題就是若是經過外部網站的連接訪問了帶中文參數的地址,且二者的編碼方式不一樣該如何解決?這個問題的解決方法我暫時也還沒想出來,但願Web編程有經驗的同窗指教,一樣的,若是文章有錯誤或紕漏也歡迎指出。