聊一聊編碼與亂碼的區別

2021-09-14 04:43:30 字數 2652 閱讀 4105

本文為飢人谷講師若愚原創文章,首發於 前端學習指南。

在瀏覽器上檢視網頁,偶爾會看到一些**出現亂碼的情況。這裡用通俗易懂的語言聊一聊編碼的那些事
計算機發明之後需要使用0和1來表示字元,於是美國人在50年代發明了 ascii (美國標準資訊交換**,american standard code for information interchange) 碼。它由128個字元組成,包括大小寫字母、數字0-9、標點符號、非列印字元(換行符、製表符等4個)以及控制字元(退格、響鈴等)組成,每個字元佔7位(1位元組是8位)。比如 'a'的 ascii碼10進製是97,二進位制是 01100001。

可以認為ascii是美國發明針對英語設計的,但歐洲人在用的時候出現了問題。對於一些特殊的拉丁字元,比如法文德文裡某些字元,ascii字符集就不包括。於是歐洲人發明了一種8位字符集是iso 8859-1latin 1,也簡稱為isolatin-1。它對ascii做了個擴充,對於0-127之間的字元還使用ascii裡的字元不變, 把位於128-255之間的字元表示拉丁字母表中特殊語言字元。

後來計算機不斷發展擴充套件到亞洲非洲,如何用計算機使用的二進位制表示這些語言又成了問題。isolatin-1的8位字符集只能表示256個字元,而僅漢語就有80000以上個字元。如何把地球上絕大多數語言用一種編碼方式表示出來呢? 於是發明了unicode編碼,只用2個位元組(16位)就可以編碼地球上幾乎所有地區的文字。

但是,unicode只是理論上的編碼方式,相當於給世界上每個文字打了個編號,但這編號具體如何在計算機裡面儲存,可以有多種實現方式。比如utf-8和gbk。

前面說了unicode只是給每個文字打了個編號,為啥不把這個編號直接轉化成二進位制儲存在計算機裡面呢? 比如英文本母s的編號是115, 用二進位制表示是00000000 1110011, 中文的編號是26085 (16進製制是65e5) ,二進位制是11001011 1100101。老外才沒那麼傻,對於老外這種日常純粹是用英文本元的人來說明明之前1個位元組就能儲存乙個字母,現在為了全球大一統非要儲存為2個位元組,相當於乙個之前乙個1m的文件,現在變為2m。於是老外耍了賴,英文本母s115沒錯,但我就用1個位元組1110011表示,而你中文26085號也沒錯,但是你不能在使用2個表示,而是用2個甚至6個位元組表示。(為了英文的特權,犧牲其他語言的儲存空間的便利),這個編碼方式就是utf-8。

utf-8(8-bit unicode transformation format)是一種針對unicode的可變長度字元編碼,又稱萬國碼。utf-8用1到6個位元組編碼unicode字元。用在網頁上可以同一頁面顯示中文簡體繁體及其它語言(如英文,日文,韓文)。

那gbk又是如何產生的呢?

這時候中國人不幹了,為啥你制定了全球大一統的規則,卻為了自己的便利又破壞規則,連這點小便宜都不放過(典型的美國人作風)? 明明用2個位元組就能表示中文乙個漢字,現在utf-8編碼中文竟然需要2個甚至4個位元組來表示。於是中國制定一套自己的規則,於是用2個位元組來表示乙個漢字,總共可以覆蓋2萬多個文字。 對於英文,好吧讓一步,還保留和你utf-8同樣的方式使用乙個位元組來表示。

下圖是把當前文章分別儲存為 gbk 何 utf-8兩種編碼格式下檔案大小的對比,表明用 gbk 確實省空間

記住:unicode只是給字元乙個代號,而gbk和utf-8使用不同的規則來表示同乙個代號。

下面這個流程是我們寫入檔案到展示檔案的簡單描述:

我們使用編輯器編寫 html 檔案

儲存編寫的html檔案

使用瀏覽器開啟html檔案

html檔案在瀏覽器展示

亂碼產生的根源就在與第2步驟和第4步。

在第4步瀏覽器開啟網頁時,它並不知道你的這個檔案是使用什麼編碼方式,於是自作主張使用了預設解碼方式。如下圖所示,檔案儲存為gbk格式,在chrome開啟時預設使用 iso -8859的解碼方式,導致編碼和解碼不匹配,產生亂碼。

那如何規避這個問題呢?即如何通知瀏覽器用什麼方式解碼呢?

首頁,在檔案儲存的時候你自己要清楚是用哪種編碼方式儲存的。如果你的檔案是儲存為utf-8格式,那麼一定要在html 的裡新增,這句話的意思是告訴瀏覽器在開啟這個頁面的時候不要去猜了,直接用utf-8去解碼。 同理,如果你的檔案儲存為gbk格式,一定在檔案裡新增

亂碼產生的根本原因是你儲存的編碼格式和瀏覽器解析時的解碼格式不匹配導致的。

亂碼一般是英文以外的字元才會出現。

為啥純粹的英文不會出現亂碼問題,即使編碼方式和解碼方式不一致?那是因為前面講過了 utf-8、gbk對英文都是採用1個位元組的編碼方式,並且使用了相同的碼字。

每日一題,每週資源推薦,精彩部落格推薦,工作、筆試、面試經驗交流解答,免費直播課,群友輕分享... ,數不盡的福利免費送

聊一聊java中過載與重寫的區別

簡單來說 重寫是子類的方法覆蓋父類的方法,要求方法名和引數都相同 過載是在同乙個類中的兩個或兩個以上的方法,擁有相同的方法名,但是引數卻不相 同,方法體也不相同,最常見的過載的例子就是類的 建構函式 可以參考api幫助文件 看看類的構造方法 舉例如下 過載 乙個類中有乙個方法a,你又在這個類中建立了...

聊一聊Iterable與Iterator的那些事!

涉及面試題 上面的面試題可以看出,其實都是一回事,只是換了一種提問方式,只要我們能掌握核心要點,隨便面試官怎麼提問,我們都能輕鬆應對!由原始碼圖可以看出,iterable有三個方法,分別是 接下來我們簡單介紹下這裡面的方法。iteratoriterator 複製 該介面主要是返回t型別的元素上的乙個...

聊一聊MyISAM和InnoDB的區別

主要有以下區別 1 mysql預設採用的是myisam。2 myisam不支援事務,而innodb支援。innodb的autocommit預設是開啟的,即每條sql語句會預設被封裝成乙個事務,自動提交,這樣會影響速度,所以最好是把多條sql語句顯示放在begin和commit之間,組成乙個事務去提交...