先簡單介紹一下編碼的狀況,咱們都知道機器上顯示的字符最終存在計算機內存裏都是以二進制碼的形式存在的。html
最開始的計算機字符只能用ASCII編碼的方式去存儲,而一個ASCII碼佔用一個字節,也就是說ASCII編碼最多隻能編碼256個字符(鍵盤上全部的半角字符)。 但爲了表示別的國家文字,就必須對原有的字符編碼方式進行擴充。而對於中文來講,主要有兩種編碼方式,分別是gb2312和gbk,前者主要是用於編碼簡體中文字符,然後者除了簡體中文字符還包括繁體中文字符。計算機迅速國際化以後,編碼便不能只侷限於英文字符和中文字符,因而出現了一個叫Unicode編碼的方式,這種編碼方式對每一個字符都使用四個字節的方式存儲,這樣一來就足夠表示全部字符了,但事實上全部的半角字符咱們只須要1個字節來表示便足夠了,所有字符都用Unicode編碼方式的話,很容易形成資源浪費的狀況,因此做爲折中的考慮,UTF-8逐漸成爲全球的流行的編碼標準,UTF-8編碼可以根據字符分別不一樣的字節大小,英文字符依然用一個字節表示,而中文有些則是兩個字節表示,有些則是三個字節。node
簡單介紹事後,如下內容所有用中文的編碼和python3.x環境(寫python代碼的時候)做爲例子。python
顧名思義,編碼就是把一個字符編碼成二進制碼存起來的方式,而解碼就是把這個二進制碼按照本來編碼的規則還原成原來的字符。windows
當咱們打開記事本,而後打下一行字符的時候,對機器來講都是一串不可識別的字符,因而咱們保存的時候,就是要對這些咱們輸入的字符進行編碼了。若是你輸入一串非英文字符,計算機會提醒你有些字符不能正確編碼(windows中文版的話沒有這種狀況,由於你按下ctrl+s計算機會有一個默認的中文編碼方式,則沒有出現沒法編碼的狀況。此處指的是英文版操做系統,固然中文操做系統也能夠自主選擇編碼方式的,請往下看~),以下圖:python3.x
這個提示是說,若是你把這個文本保存爲ANSI編碼的文本文件時,有些Unicode字符會丟失,問你是否肯定,咱們先點ok保存,看看文本效果:瀏覽器
當咱們去打開的時候,和編碼相對的概念,解碼就要用到了,系統會檢測到這個文本是一個ANSI文本,因而用ASCII編碼方式去解碼,結果沒法正常解析,出現亂碼,情理之中。(這是英文系統會出現的步驟,中文系統的測試由此處開始)。學習
咱們刪除這個文件,從新創建一個,而後輸入一樣的內容,此時不要直接保存,點擊 【文件】-->【另存爲】,下面有選擇編碼的下拉列表,個人機器記事本只能使用四種編碼方式(以下所示)測試
咱們選擇UTF-8,保存,沒有出現任何提示,打開文本,內容正常顯示(以下圖所示)。網站
而後咱們注意到寫網站的時候咱們會寫<meta charset='utf-8'>,這裏指定的utf-8是指定編碼方式仍是解碼方式呢,其實都不是,由上面所述,編碼方式取決於咱們寫完文本以後保存所選擇的編碼方式。而瀏覽器解碼呢,取決於瀏覽器的設置(這個表述並不許確,請往下看,就會明朗),這個設置固然也是能夠本身修改的,在這裏:編碼
咦,怎麼還有這個東西~
回到前面meta裏面指定的編碼有什麼用呢,這裏的編碼是你手工告訴瀏覽器說你這個網頁是使用什麼編碼去保存的,而後用瀏覽器去打開的時候,瀏覽器會用自己設置的編碼方式去解碼內容,當遇到<meta charset='utf-8'>的時候,瀏覽器會放棄設置中的方式,改用你指定的charset去解碼內容,以保證內容都能正常顯示,下面咱們來測試一下:
新建一個Test.html,用notepad++(爲了方便)打開,選擇編碼方式爲gb2312(nodepad++設置:【編碼】-->【編碼字符集】-->【中文】->【GB2312】),而後寫下代碼(以下圖所示),在這裏咱們「騙」瀏覽器說咱們用utf-8編碼(但事實上咱們是用GB2312啊):
而後用ie打開看看效果:
瀏覽器「被騙「以後,果真不能正確解碼內容了,而後咱們此時強制把瀏覽器的編碼方式設置爲GB2312,不能刷新(爲何?),結果以下:
咱們無論瀏覽器了,編輯Test.html,保存編碼方式爲UTF-8,而後刷新(此時瀏覽器編碼方式仍是GB2312),瀏覽器解析到<meta charset='utf-8'>的時候,則使用utf-8編碼方式,結果就能正常顯示.了...
在學習過程當中,不少人會拋出一串亂碼求解決方案,而不少人的建議就是使用UTF-8,反正不知道爲何,編碼錯了,就用UTF-8試試,當改爲UTF-8以後(python中就是在文件第一行加上#encoding:utf-8或者對字節碼使用.decode('utf-8')之類),還不能成功的話,接下來就不知道怎麼作了。 這種作法都只是碰運氣嘗試,並無針對性修改,當理解了這種狀況以後,面對編碼問題並不難解決。
既然問題是從python學習過程當中跑出來的,那就用python再寫一個例子好了,用open去寫文件的時候能夠傳入一個encoding參數用於指定編碼方式,一樣的,讀文件的時候encoding參數就視做解碼方式。咱們編寫如下python代碼:
path = r'C:\Test\test.txt' with open(path, 'w', encoding='gb2312') as f: f.write("測試編碼") with open(path, 'r', encoding='utf-8') as f: print(f.read())
運行查看結果,很明顯吧,解碼錯誤~
咱們用UTF-8去解碼文本,結果報錯說這不是UTF-8編碼。
把代碼 with open(path, 'r', encoding='utf-8') as f: 修改成 with open(path, 'r', encoding='gb2312') as f: ,從新運行py文件運行,結果以下
若是一開始咱們不加encoding這個參數,打印的內容也能正常顯示,由上述可知,當咱們打開一個文件的時候,系統檢測到這個文件的編碼方式,而後去解碼文件內容的,但咱們在用python讀文件的時候並無去「打開文件「這個步驟啊, 這就須要用到上述提到的#encoding:utf-8的做用了,這句註釋指定了咱們當前py文件的默認編碼方式,咱們編寫py文件的時候,都有一個默認的編碼方式,而後這份代碼的編碼和解碼(若是沒有特別指定的話),都會按照這個方式來進行,這就解釋了咱們讀的時候是應該是字節碼,打印出來倒是字符的緣由了,是python解釋器用默認編碼方式解碼,幫咱們作了這個步驟。
一樣的道理,咱們去爬一個網頁內容的時候也是,爬到的是字節碼,而後咱們要調用decode()方法對字節碼進行解碼,因此如今就知道若是出現亂碼,緣由應該從哪裏找起了吧,並非都是簡單一句「試試UTF-8」就能解決全部狀況的。
至此,以上爲本人對字符編碼與解碼的一些拙見,若有不妥之處,敬請提出斧正。
尊重知識產權,轉載引用請通知做者並註明出處!