【转】ANSI与GB2312的编码问题
ANSI與GB2312的編碼問題
前兩天和Francis討論字符編碼的問題一直到深夜1點,主要是為了解決php讀取文件的一個問題。可惜最后這個問題暫時沒解決,先拋開這個問題,我在這里總結一下我對字符編碼的認識。
文件編碼與字符編碼
首先明確一點,文件不存在什么編碼(歸根結底文件都是二進制文件,用ue打開可以看到都是一個個的16進制數),只有文件中的字符才可以說編碼。
編碼與解碼過程
字符通過某種編碼組織起來存到文件里面,計算機通過這種編碼解析解析文件,根據解析出來的文字繪制圖片顯示到顯示設備中,這樣我們就看到了文字。
常見編碼介紹
ansi編碼
最初的計算機是又8個晶體管,通過晶體管的開合與排列可以表示數種狀態,所以一個字節就定義為8bit,而一個bit只能有0,1開關的表示,2的8次方是256,所以最初的計算機只能表示256種狀態。
人們定義了前32個為狀態字符比如翻頁,換行,發出(嘟)的聲音等,后來人們為了用計算機存儲文字,又把空格,英文字母,數字等加進了進來,總共使用了127個,這時候大家把這個存儲方案叫做ANSI的ASCII編碼[American Standard Code for Information Interchange,美國信息互換標準代碼](http://www.dreamdu.com/xhtml/ascii/),這個表存儲英文已經沒有 問題了,但是127個里并不包含其它歐洲國際的文字,人們又繼續擴展ASCII表的內容,加入了一些字符,與一些畫表格的符號,直接擴展到255個。
GB2312與GBK
國人發現只使用ASCII表根本無法表示漢字!怎么辦?沒有什么能難道我們!于是我們發明了GB2312編碼,此編碼完全忽略了ASCII表中 127位后面的內容,127位前面的內容保留,如果兩個字節同時大于127(7F)就認為這兩個字節表示一個漢字,同時像標點、字母也都重新使用兩個字節 定義了一遍,這就是我們經常說的 全角,這種方案可以表示6000種文字。
但是中國的文字太復雜6000個字也不夠用,人們開始擴展GB2312,規定只要一個字節大于127,這個字節和后面的字節組合起來就代表一個漢字,這種編碼成為GBK,于是又增加了20000多個漢字!
現在明白meta的編碼信息里為什么有GB2312與GBK了吧?:)
<meta http-equiv="content-type" content="text/html; charset=GB2312" /> <meta http-equiv="content-type" content="text/html; charset=GBK" />這樣很多國家都開始定義自己的編碼了,日本,韓國等。甚至連中國的臺灣省都定義了一種編碼 BIG5。所以在當時一個程序要想適應多國語言簡直要把人郁悶死。
如果搞過windows編程的人應該知道,win里面有多字節字符集MBCS(multi-byte character set)的說法,而且MBCS包含兩種字符類型,單字節字符SBCS(single-byte characters set)和雙字節字符(double-byte characters set)DBCS。我們的GBK與GB2312都是DBCS。所以我們在編程時經常遇到一個中文字符等于兩個英文字符的事情。BIG5與日本韓國的編碼也 都屬于DBCS。
這下清楚了吧,根本沒什么ansi文件或gb2312文件,文件打開時會根據操作系統的編碼方式(就是安裝在操作系統中的編碼解析方式)來嘗試打開文件,如果安裝了中文編碼,就把ansi文件當作中文打開,如果日文編碼,就當作日文打開。
UNICODE與UTF-8
ISO最后提出了UNICODE(Universal Multiple-Octet Coded Character Set,簡稱 UCS)編碼來解決所有的問題。
UNICODE編碼方式規定使用兩個字節(16位)表示表示一個字符,算算2的16次方是多少?原來ANSI規定的都擴充為2字節,并且把所有已知的語言都編碼進UNICODE。UNICODE可以表示65536個字符。
這下多國語言程序開始高興了,使用UNICODE全部搞定!于是微軟重現編輯windows內核,完全使用UNICODE編碼,搞過win編程的人應該都知道,以A或W結尾的函數,還有靈巧的_T宏吧?
雖然UNICODE有很多優點,但是缺點也不少,我先總結我知道的兩點:
1,狂占空間,以前一個字節可以表示,現在卻要用兩個字節了,網絡上有80%屬于英文字符,這下網絡幾乎要擴大一倍!
所以又有人研究出來了UTF-8(Unicode Translation Format - 8)編碼,UNICODE轉換格式,對于常用字符使用單字節,漢字等使用雙字節。8代表每次在網絡上傳輸8位,如果是UTF-16就是每次傳輸16位。搞 過網絡編程的朋友應該知道,字節序(就是字節的排放順序)分為兩種,主機字節序與網絡字節序,就是大頭(俗稱)在前,小頭在前的問題,在網絡上面傳輸的流 的字節序很可能是不一致的,于是需要使用一種方法通知接收端,傳輸流的字節序。有人發明了一種簡單的方法,在每個流的開始加上FFEF或EFFF,分別主 機與網絡字節序,我們可以使用記事本保存一個UNICODE文件,再使用ue打開看看(HEX方式打開)。所以有時候網頁傳到網上,在網頁最開始的地方會 出現一個字符,這個有時候很令人費解。
用記事本新建立兩個文件存為UNICODE與UNICODE big endian模式,輸入夢之都,保存再用ue打開。
UNICODE
FF FE A6 68 4B 4E FD 90
UNICODE big endian
FE FF 68 A6 4E 4B 90 FD (觀察,沒兩個字節和上面的對比)
2,UNICODE與GBK等兩字節編碼完全不兼容,無法找到一種簡單的方式轉換(只能使用查找表的方式)
這點我們可以使用記事本新建立兩個文件一個ansi的文件,另一個utf8的文件,分別寫入夢之都 ,保存。使用ue的hex模式打開我們會看到。
UNICODE
FF FE A6 68 4B 4E FD 90
ansi
C3 CE D6 AE B6 BC
猜編碼
在windows系統中打開文件時,是使用了猜的方式選擇解析文件內容編碼系統,如果文件開頭使用了FEFF或FFFE,win系統認為 UNICODE編碼,否則為ANSI編碼,如果是ANSI編碼繼續分析,如果一個字節大于127,就證明這個字節與后面的字節組成了一個漢字。
所以windows中文系統下,如果ansi文件,那么就會用gb2312方式轉換,如果是日文系統,就會使用日文方式轉變,但是絕對不能說ansi文件里面有中文字符就是gb2312!一個gb2312占用兩個字節。而utf8 win系統在前面加了幾個字節以示區別。
通過這種方式分析時會產生一個很著名的問題,如果用記事本輸入“聯通”保存,再打開,發現“聯通”兩個字沒了!為什么沒有了,大家可以自己分析一下。有人說這就是聯通競爭不過移動的原因。?
通過這篇文章解決的網頁設計中的問題
- 1,一個漢字等于兩個字符,對嗎?
- 2,為什么頁面或頁面的開始會有亂碼?
- 3,GB2312與GBK的區別
- 4,為什么英文多的網站使用UTF-8比GB2312省空間?
轉載于:https://www.cnblogs.com/aaaheng/archive/2012/05/16/2503580.html
總結
以上是生活随笔為你收集整理的【转】ANSI与GB2312的编码问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SELinux让php程序无法远程连接数
- 下一篇: Web移动应用调试工具——Weinre