什麼是編碼,什麼是解碼。原理解讀

原文:http://www.cnblogs.com/luguo3000/p/3592562.html

編碼問題一直都伴隨着程序猿從不間斷,剛開始學編程的時候好多次遇到編碼問題,解 決了文件讀取的編碼問題,又遇到了網絡編碼問題,解決了網絡編碼問題又遇到了數據庫編碼問題。總結一下無非就是編碼原理沒搞清楚,希望本文能從原理上讓菜 鳥們理解編碼,遇到問題可以從原理上搞定編碼。

一.編碼

人類先有了自己的語言,交流了若干個世紀,然後出現了計算機。可惜計算機只認0和1,人類只能認文字,雙方都不能妥協,那就必須要有一個從文字到0、1的映射了。從文字到0、1的映射稱爲編碼,反過來從0、1到文字叫解碼。

具體什麼 是編碼?先來咬文嚼字一下吧。編就是將某樣東西按照一定的規則放到一起,碼在這裏是數字的意思。編碼就是將某東西編成數字。比如郵政編碼,就是將不同範圍 內的郵局編成不同的數字。計算機裏只有0和1,編碼就是將文本字符編成一系列的0和1,看起來好像是廢話啊,但這確實是編碼的本質。

後來經過編碼,計算機屏幕上終於可以顯示“Hello World”了。學計算機之前誰都不知道有這麼一個過程,因爲一切看上去都理所當然。這種根深蒂固的認識讓我們對編碼理解起來犯了難。

首先屏幕 的顯示跟計算機存儲是兩碼事,屏幕對應人們的視覺認知,它是無形的,你找不出來在哪裏刻了這麼兩個單詞,而計算機存儲是客觀存在的。計算機裏只有0和1, 怎麼來表示“Hello World”呢(假如我們在美國),那就需要將字母數字及標點符號編一個號。一個字節可以表示256個數字,表示字母數字標點足夠了,所以用一個字節就可以對應一個字符了。這樣一來計算機在顯示文字的時候,先將0、1解碼成對應的文字,然後在屏幕上渲染出來就可以了。我們將“Hello World”叫做字符,計算機實際存儲的是字符對應的編號,這些編號就叫字節流。

上邊這種編碼就是ASCII碼,如果計 算機只在美國用或者只顯示英語,那編碼就是透明的,誰都不需要去關心編碼,一切都覺得理所當然。可是計算機應用到了像中國這樣的國家,這些國家的語言哪裏 只是幾個字母啊,有成千上萬種不同的字符。很顯然ASCII碼就不能滿足需求了,怎麼辦呢,每個國家都研製自己的編碼唄,很顯然這樣做並不長久,每個國家 都有自己的編碼實在有點亂,連兩個國家的語言都不能放在一起。所以可以將世界當成一個整體,把所有的文字統一編號,這時候就出現了unicode編碼。用 一個字節來表示一個字符顯然是不夠的,unicode編碼用了兩個字節來表示一個字符。其實,編碼的發展過程並沒有這麼順利,中間還是出現了很多其他的編 碼,以後的文章可以詳細說一下幾種常用的編碼。那問題豈不是解決了,大家都用unicode不就完事了嗎,哪有這麼簡單呢,unicode出現之前計算機 領域已經有很多成型的操作系統軟件甚至標準,不可能都統一改成unicode編碼。所以到現在還是會遇到編碼問題,unicode只是給我們提供了一種統 一解釋所有文字的編碼方案。要搞清楚,這裏討論的編碼都是針對文本字符的。

二.亂碼

編碼之所以受到關注,亂碼幾乎起到了決定性的作用,如果沒有亂碼,一切都讓大家覺得順理成章,那誰還會關注編碼呢。

出現亂碼的原因就是文本字符編碼過程與字節流解碼過程使用了不同的編碼格式,這個往往歸咎於解碼格式選擇錯誤,也就是說在解碼的過程中出現了問題。如 果我的字符是用utf-8編碼,你用GBK解碼那肯定出問題。因爲文字按照utf-8的編碼規則編成的0、1,按照GBK的規則解碼回來的文字並不是原來 的文字,這時候就會出現亂碼了。這種問題會出現在文件讀寫、網絡編碼傳輸、數據庫存取上。只要牽涉到字符都有可能出現亂碼,因爲只要有字符就會有解碼過 程。

還有一種 情況就是文件壓根不是文本文件,也就是說根本就沒有經過編碼這個過程,那你去解碼當然亂碼了。比如64,你如果看做文本字符就是6和4兩個字符,可以對應 編碼格式進行編碼。如果看做是數字64,那對應的存儲結構是01000000,就沒有編碼過程,也就不需要去解碼。

要 搞清楚的一點就是同樣的文本字符,經過不同的編碼,在存儲結構上是不一樣的,但是代表的字符是一樣的,不同編碼真正的區別在於存儲結構。反過來,相同的存 儲結構,經過不同的解碼,對應的文本字符並不一樣,但是在內存上結構上並沒有改變。如果碰到亂碼,不要慌張,因爲原始存儲結構一動沒動,只不過用錯了解碼 方式。就像一千個讀者有一千個哈姆雷特一樣,真實的哈姆雷特就在那裏。

亂碼是顯示在屏幕上才被認爲是亂碼,也就是說亂碼取決於人的感官,亂碼只有人才知道﹐計算機不認爲這是亂碼。

三.文件編碼

不管是文本還是圖片或視頻,在計算機存儲上都是一視同仁,全都是字節流。但是 從方便人們閱讀的角度上還是分爲文本文件和二進制文件。文本文件的可視形式就是文本字符,在存儲和顯示時有文本字符編解碼的過程,可以直接用文本編輯器閱 讀。除文本文件以外就是二進制文件,不同類型的二進制文件都有相應的結構標準,例如java的class文件,前四個字節代表文件類型,後邊兩個字節代表 大版本號,再後邊兩個字節代表小版本號。具體哪些字節代表什麼意思,值是float類型還是int類型,都有一定的標準,所以需要特定的軟件按照標準去讀 取解析。

在不同的編程語言中,往往提供不同的類對文本文件和二進制文件進行讀寫。最常 用的就是文本文件的讀寫例如C#中有StreamReader和StreamWriter,Java中有BufferedReader和 BufferedWriter。還有二進制文件的讀寫例如C#中有BinaryReader和BinaryWriter,Java中有 DataInputStream和DataOutputStream。當然讀寫二進制文件的類也可以讀寫文本文件,因爲文本文件和二進制文件的存儲在本質 上是沒有區別的,都是二進制。只不過專門讀寫文本文件的類封裝的更好,讀寫文本文件更方便。

雲捲雲舒
原創文章 166獲贊 304訪問量 42萬+
關注 他的留言板

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章