吾國碼農(nóng)應(yīng)該都遇到過亂碼的問題,然后網(wǎng)上搜索一番添加一些設(shè)置染坯,亂碼就消失了均芽,也不繼續(xù)追究本質(zhì)。
本文試圖講清楚標題提到的概念单鹿,從此遇到亂碼從容應(yīng)對掀宋。
字符(character),就是【a】,【A】,【請】等書寫符號仲锄。
字符集(character set)劲妙,通常就是某種語言字符集合,比如英語就是ascll字符集儒喊,中文有GBK等
注意镣奋,不是每種語言只對應(yīng)一種字符集(比如GB2312 ,GBK怀愧,GB18030都包含了常用漢字侨颈,后者是前者的超集),而且字符集也不是只對應(yīng)一種語言芯义,例如Unicode字符集就包含所有語言字符,字符集只是設(shè)計者為了給字符編碼(Code Point/Numbering)設(shè)計編碼時哈垢,為了收錄到命名的字符集合,但是通常設(shè)計者都為字符集設(shè)計了對應(yīng)的編碼規(guī)范扛拨。
字符編碼(character code point),給字符集里的字符編號
編碼頁(code page)耘分,在unicode發(fā)明之前,各個地區(qū)都用2字節(jié)編碼自己的字符集,相同的編碼對應(yīng)不同的字符求泰,為了本地化央渣,windows發(fā)明了編碼頁,來對應(yīng)不同的字符集渴频。
字符編碼(character encoding)芽丹,對給定的字符編碼(code point)編碼成字節(jié)表示(byte sequence)
早期,字符被編號后枉氮,存儲時就按照編號的方式存儲志衍,沒有encoding的過程,后來發(fā)明Unicode后聊替,發(fā)現(xiàn)如果按照Unicode的編號直接存儲的話楼肪,對于英文字符就有很大存儲浪費,因為任意字符都需要2字節(jié)存儲惹悄,后來人們發(fā)明UTF-8這種編碼方式春叫,這樣UTF-8就可以一個字節(jié)表示英文字符,2個以上字節(jié)表示漢字字符泣港。
字體(Font)暂殖,定義了字符的圖形表示,現(xiàn)在的軟件展示字符時用Unicode表示当纱,字體是Unicode編碼和字符圖形的映射呛每,而以往比如WindowsCMD控制臺,沒有對應(yīng)Unicode坡氯,則用編碼頁來區(qū)分晨横,所以字體就是字符編碼金和代碼頁到字符圖形的映射。
相同字符的不同字體箫柳,顯示圖形不一樣手形。字體通常與具體的字符集相關(guān),因為字體是針對某一字符集設(shè)計的悯恍。如果用表示日語的字體顯示中文库糠,就會發(fā)現(xiàn)不一致,中日都有的漢字正常顯示涮毫,日文沒有的漢字瞬欧,就有點怪(其實是編輯器嘗試用其他字體顯示的原因)。另外可以看出罢防,字體與具體編碼無關(guān)黍判,不同編碼的同一字符,用相同字體顯示是一樣的圖形篙梢。只是字符集通常與字符編碼用相同的名稱表示,容易混淆美旧,比如GB2312,即是字符集渤滞,又是字符編碼贬墩。
好了,現(xiàn)在我們可以想象妄呕,文本文件存儲在磁盤上陶舞,都是一系列的bytes,如果不告訴文本編輯器該文件的encoding绪励,編輯器會嘗試用默認的編碼(依賴于操作系統(tǒng)設(shè)置)又或者自己探測(detect肿孵,比如文件開頭有FFEF或者EFFF字節(jié)就表明UTF-16編碼,有很多10疏魏,110開頭的字節(jié)停做,很可能是UTF-8編碼)并嘗試decode,如果沒有猜對大莫,那就會顯示亂碼蛉腌。
下面我們通過文本編寫,保存/傳輸以及瀏覽器顯示來了解一下亂碼可能的原因以及解決辦法只厘。
我們用輸入法在notepad輸入文字烙丛,輸入法首先產(chǎn)生Unicode編碼在內(nèi)存,當我們保存時編輯器首先嘗試用系統(tǒng)默認的編碼保存羔味,當我們輸入的字符不包含在本地編碼對應(yīng)的字符集時河咽,就會收到類似提示:文本包含Unicode字符,如果繼續(xù)保存則丟失信息赋元,請選擇unicode方案保存忘蟹。此時一定要選擇unicode方案保存,否則信息丟失就回天無力们陆。
好了寒瓦,接下來我們要傳輸文本到瀏覽器,一般我們只是簡單的傳輸文件(2進制流傳輸)而不對文件進行轉(zhuǎn)碼坪仇,但是瀏覽器不知道文件的編碼就有可能顯示亂碼杂腰,所以我們需要通過http頭的Content-Type: text/plain; charset=”UTF-8″來告訴瀏覽器用正確的編碼來解析。所以如果瀏覽器顯示亂碼椅文,就有一下幾種可能
1喂很,沒有content-type頭,瀏覽器默認的編碼與實際不同皆刺,嘗試調(diào)整瀏覽器編碼可以解決
2少辣,有content-type頭,但是與實際文件編碼不同羡蛾,重新制定content-type頭漓帅,或者傳送文件內(nèi)容之前對文件按照content-type頭制定的編碼進行轉(zhuǎn)碼在傳輸。
3,content-type和文件內(nèi)容都正確忙干,還是亂碼器予,瀏覽器端根本安裝沒有對應(yīng)的字符集,安裝相應(yīng)的語言(同時會安裝相應(yīng)的字符集捐迫,編碼乾翔,字體等)。
參考
https://www.w3.org/International/questions/qa-what-is-encoding
https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/
https://wenku.baidu.com/view/cb9fe505cc17552707220865.html
https://blogs.msdn.microsoft.com/shawnste/2005/03/15/whats-the-difference-between-an-encoding-code-page-character-set-and-unicode/
https://www.zhihu.com/question/21721472