編碼:編碼字符集和字符編碼

一、亂碼


首先腔寡,所有信息在計(jì)算機(jī)上都是以二進(jìn)制形式存儲(chǔ)洪添。而當(dāng)出現(xiàn)亂碼的時(shí)候往往是將這些信息以字符的形式表現(xiàn)之后垦页。這是因?yàn)橛玫木幋a和解碼的方式不一樣。
舉個(gè)例子:
當(dāng)我們將“祝皋弊椋”輸入電腦時(shí)外臂。默認(rèn)是以GB2312作為字符編碼進(jìn)行編碼,將漢字編碼成二進(jìn)制存儲(chǔ)在電腦中律胀,當(dāng)我們?cè)俅巫x取時(shí)宋光,若采用UTF-8字符編碼來解碼輸出,就會(huì)造成亂碼炭菌。
就像:
當(dāng)英國(guó)人將“祝缸锛眩”寫在紙上時(shí)。默認(rèn)是以英文來編碼黑低,將“祝缸秆蓿”的意思編碼成bless酌毡。當(dāng)一個(gè)法國(guó)人讀取時(shí),會(huì)通過法語來解碼這個(gè)單詞的意思蕾管,在法語中枷踏,bless就是“受傷”的意思。就會(huì)造成理解錯(cuò)誤掰曾,而當(dāng)如果法語如果沒有這個(gè)單詞旭蠕,就會(huì)翻譯出錯(cuò),出現(xiàn)亂碼旷坦。

二掏熬、字符集


字符集是一個(gè)規(guī)則的集合。就比如上述的英語秒梅,漢語旗芬,法語。
對(duì)于一個(gè)字符集來說捆蜀,正確編碼轉(zhuǎn)碼一個(gè)字符需要三個(gè)關(guān)鍵元素:字庫(kù)表(character repertoire)疮丛、編碼字符集(coded character set)、字符編碼(character encoding form)漱办。

其中字庫(kù)表相當(dāng)于一個(gè)所有字符的數(shù)據(jù)庫(kù)这刷。編碼字符集(編碼用的字符集)用來表示一個(gè)字符在字庫(kù)中的位置。字符編碼(字符的編碼)表示將編碼字符集轉(zhuǎn)化為實(shí)際存儲(chǔ)的數(shù)值娩井。

一般來說暇屋,會(huì)直接將編碼字符集的值作為編碼后的值直接存儲(chǔ)。例如ASCLL中A的位置是65位洞辣,編碼后的A的數(shù)值是0100 0001咐刨,即十進(jìn)制的65轉(zhuǎn)化為二進(jìn)制。

</br>
看到這里扬霜,可能有人會(huì)疑惑:既然每個(gè)字符都有自己的編號(hào)(編碼字符集)定鸟,那直接存儲(chǔ)就好了啊,為什么還要字符編碼呢著瓶?

其實(shí)原因也比較好理解联予,unicode的出現(xiàn)是為了統(tǒng)一字庫(kù)表,能夠涵蓋世界上所有的字符材原,但實(shí)際使用過程中會(huì)發(fā)現(xiàn)真正用的上的字符相對(duì)整個(gè)字庫(kù)表來說比例非常低沸久。例如中文地區(qū)的程序幾乎不會(huì)需要日語字符,而一些英語國(guó)家甚至簡(jiǎn)單的ASCII字庫(kù)表就能滿足基本需求余蟹。而如果把每個(gè)字符都用字庫(kù)表中的序號(hào)來存儲(chǔ)的話卷胯,每個(gè)字符就需要3個(gè)字節(jié)(這里以Unicode字庫(kù)為例),這樣對(duì)于原本用僅占一個(gè)字符的ASCII編碼的英語地區(qū)國(guó)家顯然是一個(gè)額外成本(存儲(chǔ)體積是原來的三倍)威酒。算的直接一些窑睁,同樣一塊硬盤挺峡,用ASCII可以存1500篇文章,而用3字節(jié)Unicode序號(hào)存儲(chǔ)只能存500篇担钮。于是就出現(xiàn)了UTF-8這樣的變長(zhǎng)編碼橱赠。在UTF-8編碼中原本只需要一個(gè)字節(jié)的ASCII字符,仍然只占一個(gè)字節(jié)裳朋。而像中文及日語這樣的復(fù)雜字符就需要2個(gè)到3個(gè)字節(jié)來存儲(chǔ)病线。

UTF-8和Unicode的關(guān)系
看完上面的解釋,那么對(duì)于UTF-8和Unicode的關(guān)系就比較好理解了鲤嫡。unicode就是上面的編碼字符集,而utf-8就是字符編碼绑莺。也可以理解為unicode是字符在字庫(kù)里的位置暖眼,或者unicode代表整個(gè)字庫(kù)。
unicode幾乎包括了所有國(guó)家的可能出現(xiàn)的所有字符纺裁。Unicode的編號(hào)從0000開始一直到10FFFF共分為16個(gè)Plane诫肠,每個(gè)Plane中有65536個(gè)字符。而UTF-8則只實(shí)現(xiàn)了第一個(gè)Plane欺缘,可見UTF-8雖然是一個(gè)當(dāng)今接受度最廣的字符集編碼栋豫,但是它并沒有涵蓋整個(gè)Unicode的字庫(kù),這也造成了它在某些場(chǎng)景下對(duì)于特殊字符的處理困難谚殊。

UTF-8編碼簡(jiǎn)介
為了更好的理解后面的實(shí)際應(yīng)用丧鸯,我們這里簡(jiǎn)單的介紹下UTF-8的編碼實(shí)現(xiàn)方法。即UTF-8的物理存儲(chǔ)和Unicode序號(hào)的轉(zhuǎn)換關(guān)系嫩絮。
UTF-8編碼為變長(zhǎng)編碼丛肢。最小編碼單位(code unit)為一個(gè)字節(jié)。一個(gè)字節(jié)的前1-3個(gè)bit為描述性部分剿干,后面為實(shí)際序號(hào)部分蜂怎。
1、如果一個(gè)字節(jié)的第一位為0置尔,那么代表當(dāng)前字符為單字節(jié)字符杠步,占用一個(gè)字節(jié)的空間。0之后的所有部分(7個(gè)bit)代表在Unicode中的序號(hào)榜轿。
2幽歼、如果一個(gè)字節(jié)以110開頭,那么代表當(dāng)前字符為雙字節(jié)字符差导,占用2個(gè)字節(jié)的空間试躏。110之后的所有部分(7個(gè)bit)代表在Unicode中的序號(hào)。且第二個(gè)字節(jié)以10開頭
3设褐、如果一個(gè)字節(jié)以1110開頭颠蕴,那么代表當(dāng)前字符為三字節(jié)字符泣刹,占用2個(gè)字節(jié)的空間。110之后的所有部分(7個(gè)bit)代表在Unicode中的序號(hào)犀被。且第二椅您、第三個(gè)字節(jié)以10開頭
4、如果一個(gè)字節(jié)以10開頭寡键,那么代表當(dāng)前字節(jié)為多字節(jié)字符的第二個(gè)字節(jié)掀泳。10之后的所有部分(6個(gè)bit)代表在Unicode中的序號(hào)。
具體每個(gè)字節(jié)的特征可見下表西轩,其中x代表序號(hào)部分员舵,把各個(gè)字節(jié)中的所有x部分拼接在一起就組成了在Unicode字庫(kù)中的序號(hào)

UTF編碼

例如“漢”字的Unicode編碼是6C49。6C49在0800-FFFF之間藕畔,所以肯定要用3字節(jié)模板了:1110xxxx 10xxxxxx 10xxxxxx马僻。將6C49寫成二進(jìn)制是:0110 110001 001001,用這個(gè)比特流依次代替模板中的x注服,得到:11100110 10110001 10001001韭邓,即E6 B1 89。

其中iso 8859-1,gb2312,gbk,gb18030,big5,unicode等都是編碼字符集和字符編碼一致的字符集溶弟,其中女淑,unicode還有好幾種字符編碼,比如UTF-8辜御,UTF-16等等鸭你。

<br />

三、亂碼解決


根據(jù)上訴內(nèi)容我抠,可以知道大部分的亂碼都是由解碼編碼不統(tǒng)一引起的(iso8859-1解碼中文也會(huì)亂碼)苇本,那我們?cè)趺唇鉀Q呢?
其實(shí)只要分析每個(gè)需要解碼的過程菜拓,一一分析就可以知道了瓣窄。以web應(yīng)用為例:
首先在jsp上面有一行不可或缺的代碼<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
pageEncoding是jsp文件本身的編碼
contentType的charset是指服務(wù)器發(fā)送給客戶端時(shí)的內(nèi)容編碼

JSP要經(jīng)過兩次的“編碼”,第一階段會(huì)用pageEncoding纳鼎,第二階段會(huì)用utf-8至utf-8俺夕,第三階段就是由Tomcat出來的網(wǎng)頁(yè), 用的是contentType贱鄙。

第一階段是jsp編譯成.java劝贸,它會(huì)根據(jù)pageEncoding的設(shè)定讀取jsp,結(jié)果是由指定的編碼方案翻譯成統(tǒng)一的UTF-8 JAVA源碼(即.java)逗宁,如果pageEncoding設(shè)定錯(cuò)了映九,或沒有設(shè)定,出來的就是中文亂碼瞎颗。

第二階段是由JAVAC的JAVA源碼至java byteCode的編譯件甥,不論JSP編寫時(shí)候用的是什么編碼方案捌议,經(jīng)過這個(gè)階段的結(jié)果全部是UTF-8的encoding的java源碼。

JAVAC用UTF-8的encoding讀取java源碼引有,編譯成UTF-8 encoding的二進(jìn)制碼(即.class)瓣颅,這是JVM對(duì)常數(shù)字串在二進(jìn)制碼(java encoding)內(nèi)表達(dá)的規(guī)范。

第三階段是Tomcat(或其的application container)載入和執(zhí)行階段二的來的JAVA二進(jìn)制碼譬正,輸出的結(jié)果宫补,也就是在客戶端見到的,這時(shí)隱藏在階段一和階段二的參數(shù)contentType就發(fā)揮了功效

參考文獻(xiàn):
Notepad++的多種編碼支持
編譯.java文件時(shí)的編碼問題
【筆面試】字符流和字節(jié)流的區(qū)別以及如何解決亂碼問題
jsp中的contentType與pageEncoding的區(qū)別和作用
漢字編碼轉(zhuǎn)換原理及方法

四曾我、Notepad++


而像Notepad++等軟件粉怕,有兩種功能


Notepad++

以XXX格式編碼是改變編碼字符集,意味著在電腦中存儲(chǔ)的值是不變的
轉(zhuǎn)為XXX格式編碼是改變編碼格式抒巢,意味著都是同一個(gè)字符集斋荞,改變的是編碼方式,比如UTF-8轉(zhuǎn)UTF-16

utf8mb4可以放表情虐秦,4個(gè)字節(jié)
utf8_bin將字符串中的每一個(gè)字符用二進(jìn)制數(shù)據(jù)存儲(chǔ),區(qū)分大小寫凤优。

utf8_genera_ci不區(qū)分大小寫悦陋,ci為case insensitive的縮寫,即大小寫不敏感筑辨。

utf8_general_cs區(qū)分大小寫俺驶,cs為case sensitive的縮寫,即大小寫敏感棍辕。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末暮现,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子楚昭,更是在濱河造成了極大的恐慌栖袋,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抚太,死亡現(xiàn)場(chǎng)離奇詭異塘幅,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)尿贫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門电媳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人庆亡,你說我怎么就攤上這事匾乓。” “怎么了又谋?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵拼缝,是天一觀的道長(zhǎng)娱局。 經(jīng)常有香客問我,道長(zhǎng)珍促,這世上最難降的妖魔是什么铃辖? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮猪叙,結(jié)果婚禮上娇斩,老公的妹妹穿的比我還像新娘。我一直安慰自己穴翩,他們只是感情好犬第,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著芒帕,像睡著了一般歉嗓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上背蟆,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天鉴分,我揣著相機(jī)與錄音,去河邊找鬼带膀。 笑死志珍,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的垛叨。 我是一名探鬼主播伦糯,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼嗽元!你這毒婦竟也來了敛纲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤剂癌,失蹤者是張志新(化名)和其女友劉穎淤翔,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體珍手,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡办铡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了琳要。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寡具。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖稚补,靈堂內(nèi)的尸體忽然破棺而出童叠,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布厦坛,位于F島的核電站五垮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏杜秸。R本人自食惡果不足惜放仗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望撬碟。 院中可真熱鬧诞挨,春花似錦、人聲如沸呢蛤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)其障。三九已至银室,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間励翼,已是汗流浹背蜈敢。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留汽抚,地道東北人扶认。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像殊橙,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子狱从,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 原文在這里:各種字符集和編碼詳解 在軟件的編碼和實(shí)現(xiàn)中膨蛮,我們可能會(huì)碰到個(gè) 一個(gè)比較頭疼的問題--編碼,不同字符間的...
    舌尖上的大胖閱讀 1,793評(píng)論 0 2
  • 亂碼 亂碼是怎么出現(xiàn)的呢季研?對(duì)同一組二進(jìn)制數(shù)據(jù)敞葛,不同的編碼會(huì)解析出不同的字符,用對(duì)了編碼与涡,解析出來的字符組成的文字是...
    __Jasmine__閱讀 617評(píng)論 0 0
  • 0 前言 在平時(shí)的開發(fā)過程中大部分人應(yīng)該都遇到過中文亂碼問題惹谐,瀏覽網(wǎng)頁(yè)時(shí)也會(huì)遇到內(nèi)容顯示亂碼的情況,一般遇到這種情...
    小豬啊嗚閱讀 2,579評(píng)論 1 10
  • ——“極簡(jiǎn)主義生活是近年來的流行新趨勢(shì)怎囚,是對(duì)自由的重新定義。它強(qiáng)調(diào)相對(duì)于“物”而言桥胞,生活方式應(yīng)當(dāng)由“人”所主導(dǎo)恳守】加ぃ”...
    暮依閱讀 1,259評(píng)論 0 0
  • 北京街上的女孩同貴陽(yáng)街上的女孩穿著一樣的衣服,討論著一樣的減肥話題催烘。追捧一樣的包包沥阱,看一樣的韓劇。上海的青年同...
    量子時(shí)空閱讀 666評(píng)論 0 0