一知半解說亂碼,Unicode,utf-8 和ASCII碼- 台部落
文章推薦指數: 80 %
一知半解說亂碼,Unicode,utf-8 和ASCII碼. 原創 da_yun 2018-09-11 07:24. 自學編程的菜鳥一隻。
前半片菜鳥總結,後半片,貼了一篇前人博客。
請輸入正確的登錄賬號或密碼
註冊
忘記密碼
首頁
python/shell
正文
一知半解說亂碼,Unicode,utf-8和ASCII碼
原創
da_yun
2018-09-1107:24
自學編程的菜鳥一隻。
前半片菜鳥總結,後半片,貼了一篇前人博客。
一直不明白爲什麼,讓程序打印中文,或者顯示中文時,會是亂碼。
查資料,或者網上查,只是說是因爲編碼的的原因,聲明一下就可以,比如Python首行加入#coding=utf-8 ,#-*-coding:utf-8-*- html在head標籤內加入
爲什麼???現在用的是win7中文版,編輯器notepad++360瀏覽器,爲了方便就用html舉個例子吧,其他程序感覺都是一個道理。
我是小六兒,大運
/html>用360瀏覽器打開,顯示爲亂碼。此時在頁面上右鍵,點擊編碼,可以看到瀏覽器默認解碼的編碼格式是中文簡體GBK,這是中文編碼的一種格式。
那麼我寫的那三行html的代碼是什麼編碼格式保存的呢?查看notepad++編輯器,默認的編碼格式是utf-8無bom格式編碼,不知道什麼是bom,就當是utf-8的編碼吧。
哦,現在有點兒明白了,我寫的着三行代碼,是用utf-8的編碼格式保存的,用瀏覽器打開是,瀏覽器默認是解釋GBK格式,所以把utf-8格式的內容“我是小六兒,大運”當個GBK格式的編碼來解碼,可不就成了亂碼。
這樣解釋,還能說通。
如果是上邊我總結的那樣,那麼接下來我們就來驗證一下邊的三點猜想是否正確。
1、在head標籤內加入
2、在head標籤內加入
3、在head標籤內不加入
接下來,就先1,在head標籤內加入
我是小六兒,大運
這是360瀏覽器,能正常顯示中文,而且解碼的編碼格式爲utf-8,也就是這個標籤再接下來,我們就驗證猜想2,加入
ANSI是默認的編碼方式。
對於英文文件是ASCII編碼,對於簡體中文文件是GB2312編碼(只針對Windows簡體中文版,如果是繁體中文版會採用Big5碼)。
GB2312就是中文編碼格式,GB2312是中國規定的漢字編碼,也可以說是簡體中文的字符集編碼;GBK是GB2312的擴展,除了兼容GB2312外,它還能顯示繁體中文,還有日文的假名這裏我們選擇ANSI就把它當成GBK吧。
把notepad++格式改爲ANSI,此時代碼中的文字直接變成了亂碼,這時可以刪了重新寫。
下圖爲修改格式後,原來的稱爲亂碼。
下圖爲,把亂碼刪除,重新輸入。
在瀏覽器中運行後,以utu-8格式來解碼,顯示爲亂碼,我們的猜想正確。
接下來我們來驗證第三個猜想,在head標籤內不加入
在代碼中去掉
用瀏覽器運行後,中文能夠正常顯示,且編碼默認的還是GBK。
第三個猜想正確。
在python中可以吧瀏覽器類比成python解釋器,道理相同,本人沒有深入瞭解,文本編碼的原理。
只是通過驗證,把思路理順,貌似能夠說得通。
歡迎指正期間讀了一篇下來10年前的博客,順便貼下來,再此感謝下文博客作者阮老師的分享。
鏈接:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html ASCII碼我們知道,在計算機內部,所有的信息最終都表示爲一個二進制的字符串。
每一個二進制位(bit)有0和1兩種狀態,因此八個二進制位就可以組合出256種狀態,這被稱爲一個字節(byte)。
也就是說,一個字節一共可以用來表示256種不同的狀態,每一個狀態對應一個符號,就是256個符號,從0000000到11111111。
上個世紀60年代,美國製定了一套字符編碼,對英語字符與二進制位之間的關係,做了統一規定。
這被稱爲ASCII碼,一直沿用至今。
ASCII碼一共規定了128個字符的編碼,比如空格"SPACE"是32(二進制00100000),大寫的字母A是65(二進制01000001)。
這128個符號(包括32個不能打印出來的控制符號),只佔用了一個字節的後面7位,最前面的1位統一規定爲0。
2、非ASCII編碼英語用128個符號編碼就夠了,但是用來表示其他語言,128個符號是不夠的。
比如,在法語中,字母上方有注音符號,它就無法用ASCII碼錶示。
於是,一些歐洲國家就決定,利用字節中閒置的最高位編入新的符號。
比如,法語中的é的編碼爲130(二進制10000010)。
這樣一來,這些歐洲國家使用的編碼體系,可以表示最多256個符號。
但是,這裏又出現了新的問題。
不同的國家有不同的字母,因此,哪怕它們都使用256個符號的編碼方式,代表的字母卻不一樣。
比如,130在法語編碼中代表了é,在希伯來語編碼中卻代表了字母Gimel(),在俄語編碼中又會代表另一個符號。
但是不管怎樣,所有這些編碼方式中,0--127表示的符號是一樣的,不一樣的只是128--255的這一段。
至於亞洲國家的文字,使用的符號就更多了,漢字就多達10萬左右。
一個字節只能表示256種符號,肯定是不夠的,就必須使用多個字節表達一個符號。
比如,簡體中文常見的編碼方式是GB2312,使用兩個字節表示一個漢字,所以理論上最多可以表示256x256=65536個符號。
中文編碼的問題需要專文討論,這篇筆記不涉及。
這裏只指出,雖然都是用多個字節表示一個符號,但是GB類的漢字編碼與後文的Unicode和UTF-8是毫無關係的。
3.Unicode正如上一節所說,世界上存在着多種編碼方式,同一個二進制數字可以被解釋成不同的符號。
因此,要想打開一個文本文件,就必須知道它的編碼方式,否則用錯誤的編碼方式解讀,就會出現亂碼。
爲什麼電子郵件常常出現亂碼?就是因爲發信人和收信人使用的編碼方式不一樣。
可以想象,如果有一種編碼,將世界上所有的符號都納入其中。
每一個符號都給予一個獨一無二的編碼,那麼亂碼問題就會消失。
這就是Unicode,就像它的名字都表示的,這是一種所有符號的編碼。
Unicode當然是一個很大的集合,現在的規模可以容納100多萬個符號。
每個符號的編碼都不一樣,比如,U+0639表示阿拉伯字母Ain,U+0041表示英語的大寫字母A,U+4E25表示漢字"嚴"。
具體的符號對應表,可以查詢unicode.org,或者專門的漢字對應表。
4.Unicode的問題需要注意的是,Unicode只是一個符號集,它只規定了符號的二進制代碼,卻沒有規定這個二進制代碼應該如何存儲。
比如,漢字"嚴"的unicode是十六進制數4E25,轉換成二進制數足足有15位(100111000100101),也就是說這個符號的表示至少需要2個字節。
表示其他更大的符號,可能需要3個字節或者4個字節,甚至更多。
這裏就有兩個嚴重的問題,第一個問題是,如何才能區別Unicode和ASCII?計算機怎麼知道三個字節表示一個符號,而不是分別表示三個符號呢?第二個問題是,我們已經知道,英文字母只用一個字節表示就夠了,如果Unicode統一規定,每個符號用三個或四個字節表示,那麼每個英文字母前都必然有二到三個字節是0,這對於存儲來說是極大的浪費,文本文件的大小會因此大出二三倍,這是無法接受的。
它們造成的結果是:1)出現了Unicode的多種存儲方式,也就是說有許多種不同的二進制格式,可以用來表示Unicode。
2)Unicode在很長一段時間內無法推廣,直到互聯網的出現。
5.UTF-8互聯網的普及,強烈要求出現一種統一的編碼方式。
UTF-8就是在互聯網上使用最廣的一種Unicode的實現方式。
其他實現方式還包括UTF-16(字符用兩個字節或四個字節表示)和UTF-32(字符用四個字節表示),不過在互聯網上基本不用。
重複一遍,這裏的關係是,UTF-8是Unicode的實現方式之一。
UTF-8最大的一個特點,就是它是一種變長的編碼方式。
它可以使用1~4個字節表示一個符號,根據不同的符號而變化字節長度。
UTF-8的編碼規則很簡單,只有二條:1)對於單字節的符號,字節的第一位設爲0,後面7位爲這個符號的unicode碼。
因此對於英語字母,UTF-8編碼和ASCII碼是相同的。
2)對於n字節的符號(n>1),第一個字節的前n位都設爲1,第n+1位設爲0,後面字節的前兩位一律設爲10。
剩下的沒有提及的二進制位,全部爲這個符號的unicode碼。
下表總結了編碼規則,字母x表示可用編碼的位。
Unicode符號範圍|UTF-8編碼方式(十六進制)|(二進制)--------------------+---------------------------------------------00000000-0000007F|0xxxxxxx00000080-000007FF|110xxxxx10xxxxxx00000800-0000FFFF|1110xxxx10xxxxxx10xxxxxx00010000-0010FFFF|11110xxx10xxxxxx10xxxxxx10xxxxxx跟據上表,解讀UTF-8編碼非常簡單。
如果一個字節的第一位是0,則這個字節單獨就是一個字符;如果第一位是1,則連續有多少個1,就表示當前字符佔用多少個字節。
下面,還是以漢字"嚴"爲例,演示如何實現UTF-8編碼。
已知"嚴"的unicode是4E25(100111000100101),根據上表,可以發現4E25處在第三行的範圍內(00000800-0000FFFF),因此"嚴"的UTF-8編碼需要三個字節,即格式是"1110xxxx10xxxxxx10xxxxxx"。
然後,從"嚴"的最後一個二進制位開始,依次從後向前填入格式中的x,多出的位補0。
這樣就得到了,"嚴"的UTF-8編碼是"111001001011100010100101",轉換成十六進制就是E4B8A5。
6.Unicode與UTF-8之間的轉換通過上一節的例子,可以看到"嚴"的Unicode碼是4E25,UTF-8編碼是E4B8A5,兩者是不一樣的。
它們之間的轉換可以通過程序實現。
在Windows平臺下,有一個最簡單的轉化方法,就是使用內置的記事本小程序Notepad.exe。
打開文件後,點擊"文件"菜單中的"另存爲"命令,會跳出一個對話框,在最底部有一個"編碼"的下拉條。
裏面有四個選項:ANSI,Unicode,Unicodebigendian和UTF-8。
1)ANSI是默認的編碼方式。
對於英文文件是ASCII編碼,對於簡體中文文件是GB2312編碼(只針對Windows簡體中文版,如果是繁體中文版會採用Big5碼)。
2)Unicode編碼指的是UCS-2編碼方式,即直接用兩個字節存入字符的Unicode碼。
這個選項用的littleendian格式。
3)Unicodebigendian編碼與上一個選項相對應。
我在下一節會解釋littleendian和bigendian的涵義。
4)UTF-8編碼,也就是上一節談到的編碼方法。
選擇完"編碼方式"後,點擊"保存"按鈕,文件的編碼方式就立刻轉換好了。
7.Littleendian和Bigendian上一節已經提到,Unicode碼可以採用UCS-2格式直接存儲。
以漢字"嚴"爲例,Unicode碼是4E25,需要用兩個字節存儲,一個字節是4E,另一個字節是25。
存儲的時候,4E在前,25在後,就是Bigendian方式;25在前,4E在後,就是Littleendian方式。
這兩個古怪的名稱來自英國作家斯威夫特的《格列佛遊記》。
在該書中,小人國裏爆發了內戰,戰爭起因是人們爭論,吃雞蛋時究竟是從大頭(Big-Endian)敲開還是從小頭(Little-Endian)敲開。
爲了這件事情,前後爆發了六次戰爭,一個皇帝送了命,另一個皇帝丟了王位。
因此,第一個字節在前,就是"大頭方式"(Bigendian),第二個字節在前就是"小頭方式"(Littleendian)。
那麼很自然的,就會出現一個問題:計算機怎麼知道某一個文件到底採用哪一種方式編碼?Unicode規範中定義,每一個文件的最前面分別加入一個表示編碼順序的字符,這個字符的名字叫做"零寬度非換行空格"(ZEROWIDTHNO-BREAKSPACE),用FEFF表示。
這正好是兩個字節,而且FF比FE大1。
如果一個文本文件的頭兩個字節是FEFF,就表示該文件採用大頭方式;如果頭兩個字節是FFFE,就表示該文件採用小頭方式。
8.實例下面,舉一個實例。
打開"記事本"程序Notepad.exe,新建一個文本文件,內容就是一個"嚴"字,依次採用ANSI,Unicode,Unicodebigendian和UTF-8編碼方式保存。
然後,用文本編輯軟件UltraEdit中的"十六進制功能",觀察該文件的內部編碼方式。
1)ANSI:文件的編碼就是兩個字節"D1CF",這正是"嚴"的GB2312編碼,這也暗示GB2312是採用大頭方式存儲的。
2)Unicode:編碼是四個字節"FFFE254E",其中"FFFE"表明是小頭方式存儲,真正的編碼是4E25。
3)Unicodebigendian:編碼是四個字節"FEFF4E25",其中"FEFF"表明是大頭方式存儲。
4)UTF-8:編碼是六個字節"EFBBBFE4B8A5",前三個字節"EFBBBF"表示這是UTF-8編碼,後三個"E4B8A5"就是"嚴"的具體編碼,它的存儲順序與編碼順序是一致的。
亂碼 utf 編碼格式 Python/shell 發表評論 登录 所有評論 還沒有人評論,想成為第一個評論的人麼?請在上方評論欄輸入並且點擊發布. 相關文章 Asp常用通用函數之Cookie防亂碼 youyaozc 2019-02-2313:43:04 繁體中文網頁亂碼 Monkey001 2019-02-2313:19:41 深入淺出URL編碼 ketqi 2019-02-2312:50:43 linux下windows文件名亂碼解決方法 k1nman 2019-02-2300:41:53 SublimeText3中文亂碼問題 CACZJZ 2019-02-2300:24:09 亂碼 vivisrf 2019-02-2300:23:08 gedit亂碼問題 wenix 2019-02-2300:16:40 ubuntu下使用vi是方向鍵變亂碼退格鍵不能使用的解決方法 adam1943 2019-02-2300:10:11 RHEL5.1安裝VMTOOL及中文亂碼終極解決方案 waither12 2019-02-2300:08:50 java亂碼問題 FarXiang 2019-02-2300:05:45 C#中面向連接Socket編程(結合Encoding與線程池) sunzongbao2007 2019-02-2300:01:27 struts處理中文亂碼問題總結 rxtcc 2019-02-2223:58:03 Linux與SecureCRT的使用、消除亂碼、基本命令使用 jacinto 2019-02-2223:56:15 用python連接Oracle是總是亂碼 benhuang138 2019-02-2223:36:30 linux命令行下中文文件名亂碼的解決方法 hualsj88 2019-02-2223:31:06 D da_yun 24小時熱門文章 k8s入門之常見問題&命令 鬱金香用C寫一個定時器來循環獲取陽光 這個外包公司太噁心了。
。
進去請三思! 11導師讓你造航母怎麼辦? 10我可以不用發論文了? 一文讀懂MySQL索引 驅動開發:內核R3與R0內存映射拷貝 驅動開發:內核通過PEB得到進程參數 vscodemarkdownWYSIWYG所見即所得編輯和預覽 最新文章 Linux命令(命令學習之一) linux命令學習之系統管理類命令(命令學習之二) bash特性一、二、三 linux用戶的創建與管理(命令學習之五) linux命令學習之cp(命令學習之四) 最新評論文章 [2022]TopRatedCheckPoint156-315.80ExamQuestions QualifiedWritingServiceinAustraliacanallowstudentstoachievebettergrades Takeassignmenthelpertoresolvethepaperquerieseasily UpdatedCompTIADA0-001ExamQuestions(2022) 美國黑金效果和其它速效藥的不同之處 MicrosoftDP-500PDFQuestion[2022]-SecretToPassExamInFirstAttempt-[PremiumDumps]
延伸文章資訊
- 1PHP亂碼問題,UTF-8亂碼常見問題小結@ 凝視、散記 - 隨意窩
例如,您可以從彈出式選單中選取「XHTML 1.0 Transitional」或「XHTML 1.0 Strict」,使HTML 文件與XHTML 相容。 編碼: 會指定文件中字元所用的編碼方式...
- 2中文亂碼之《字符編碼:ASCII,Unicode 和UTF-8》 - 程式人生
中文亂碼之《字符編碼:ASCII,Unicode 和UTF-8》. 阿新• • 發佈:2019-01-26. 不同的簡體中文block 怎麽一個默認lock .html 理論 ...
- 3利用編碼設定解決亂碼問題- Google Merchant Center說明
如果您打開.txt 檔的Google 產品分類時發現內容是亂碼,請更新瀏覽器的編碼設定,以正確顯示產品分類。 ... 選取[文字編碼]。 在下拉式選單中選取[Unicode (UTF-8)]。
- 4記事本中文會自動亂碼? - Microsoft 社群
- 5Day27 Python 基礎- 字符轉編碼操作 - iT 邦幫忙
UTF-8 是一種針對Unicode的可變長度字元編碼,英文字符一樣會依照ASCII碼 ... 上面那個看起來很像亂碼(不是亂馬),其實是unicode格式,証明我們已經確實的把 UTF-8 ...