本文大量借鑒了https://www.cnblogs.com/notbecoder/p/4840783.html里面的內(nèi)容
概述
什么是字符腺怯、字符集和字符編碼毛嫉?
字符指的是文字或者符號诽俯。
字符集指的是字符的集合,一般字符集是一個完備的字符庫承粤,里面的字符足夠表意暴区。
人與人之間用于交流的文字符號,計算機(jī)并不能理解辛臊,也不能處理仙粱。為了讓人與計算機(jī)、計算機(jī)與計算機(jī)之間可以正常交流浪讳,人發(fā)明了各種計算機(jī)字符集缰盏、字符編碼。
字符集只是字符的集合淹遵,里面的每個字符都會對應(yīng)一個字符代碼口猜,如ASCII碼中"a"對應(yīng)數(shù)字97。但是字符代碼不一定適合作網(wǎng)絡(luò)傳送透揣、處理济炎,有時字符須經(jīng)過編碼(encode)后才能應(yīng)用,這就是字符編碼辐真。我們常用的ASCII碼须尚、GBK崖堤、GB2312等字符集,除了具有字符集層面的含義之外耐床,還具有字符編碼的意思(也就是字符代碼和字符編碼是一樣的)密幔。但我們常用的Unicode字符集(兩個字節(jié)),根據(jù)不同的使用需要撩轰,會將字符重新編碼胯甩,比如UTF8(不定長,1 ~ 8字節(jié))堪嫂、UTF16(不定長偎箫,2 ~ 4字節(jié))、UTF32(定長皆串,4字節(jié))都是Unicode字符集的編碼實(shí)現(xiàn)淹办。
計算機(jī)中的字符集和字符編碼
因?yàn)橛嬎銠C(jī)只能理解二進(jìn)制,計算機(jī)中恶复,是使用二進(jìn)制字節(jié)的方式表示字符怜森。在計算機(jī)中建立一種編碼模型需要下面四步:
1、要有一個字符庫寂玲,確定這些字符足夠表意塔插。 比如ASCII字符集,已經(jīng)足夠表示英語拓哟,但不能表示中文,于是產(chǎn)生GB2312字符集伶授。所以市面上有很多字符集断序,經(jīng)常會出現(xiàn)亂碼問題
2、第一層編碼糜烹,給每個字符編個數(shù)字违诗,英文叫Code Point 或 Code Position。比如ASCII字符集中疮蹦,65表示“A”诸迟,97表示“a”。
3愕乎、第二層編碼阵苇,確定表示字符的二進(jìn)制位數(shù)(8位,16位感论,32位)绅项。ASCII使用7位(01000001表示“A”),DBCS(雙字節(jié)字符集)使用16位比肄。
4快耿、第三層編碼囊陡,確定字符二進(jìn)制值的存儲格式(大端法,小端法)
常見的字符集和字符編碼
ASCII編碼
我們經(jīng)常說ASCII時掀亥,包含了字符集和字符編碼兩種意思撞反。ASCII碼是英文字符集,使用一個字節(jié)編碼一個字符(一開始的ASCII用7 bits表示一個字節(jié)搪花,第8位空余)痢畜,這套字符編碼,已經(jīng)可以完全涵蓋英文字符鳍侣。不過對于日文丁稀、韓文和漢字來說,是完全不夠用的倚聚。所以很多國家發(fā)明了自己的字符集和字符編碼线衫,但一般都兼容了ASCII碼。
ISO-8859編碼
由于各公司惑折、國家之間都有自己的字符集授账,同一個數(shù)值,在不同的字符集之間表示的符號可能不一樣惨驶,這樣在一臺電腦上正嘲兹龋可以閱讀的文件,到另外一臺電腦可能就成了亂碼粗卜。為了解決這個問題屋确,ISO組織統(tǒng)一了一套標(biāo)準(zhǔn)字符集,就是ISO-8859.不過 ISO-8859 不是一個字符集续扔,而是一系列擴(kuò)充的ASCII碼字符集攻臀。ISO-8859也是單字節(jié)字符集,用一個字節(jié)表示一個字符纱昧。
ISO/IEC 8859-1 (Latin-1) - 西歐語言
ISO/IEC 8859-2 (Latin-2) - 中歐語言
ISO/IEC 8859-3 (Latin-3) - 南歐語言刨啸。世界語也可用此字符集顯示。
ISO/IEC 8859-4 (Latin-4) - 北歐語言
ISO/IEC 8859-5 (Cyrillic) - 斯拉夫語言
ISO/IEC 8859-6 (Arabic) - 阿拉伯語
ISO/IEC 8859-7 (Greek) - 希臘語
ISO/IEC 8859-8 (Hebrew) - 希伯來語(視覺順序)
ISO 8859-8-I - 希伯來語(邏輯順序)
ISO/IEC 8859-9(Latin-5 或 Turkish)- 它把Latin-1的冰島語字母換走识脆,加入土耳其語字母设联。
ISO/IEC 8859-10(Latin-6 或 Nordic)- 北日耳曼語支,用來代替Latin-4灼捂。
ISO/IEC 8859-11 (Thai) - 泰語离例,從泰國的 TIS620 標(biāo)準(zhǔn)字集演化而來。
ISO/IEC 8859-13(Latin-7 或 Baltic Rim)- 波羅的語族
ISO/IEC 8859-14(Latin-8 或 Celtic)- 凱爾特語族
ISO/IEC 8859-15 (Latin-9) - 西歐語言纵东,加入Latin-1欠缺的芬蘭語字母和大寫法語重音字母粘招,以及歐元(€)符號。
ISO/IEC 8859-16 (Latin-10) - 東南歐語言偎球。主要供羅馬尼亞語使用洒扎,并加入歐元符號辑甜。
GBK編碼
GBK字符集是漢字字符集,每兩個字節(jié)表示一個字符袍冷,兼容了ASCII碼磷醋,屬于定長編碼。
Unicode字符集
上面介紹的字符集都屬于本地字符集胡诗,在一國之內(nèi)使用沒問題邓线,跨國就不行了。如果一個計算機(jī)只能識別ACSII碼集煌恢,要展示漢字就亂碼了骇陈。而且每個國家都使用自己的字符集的話,會經(jīng)常遇到亂碼問題瑰抵,不利于信息的傳輸和知識的傳播你雌,對電腦和互聯(lián)網(wǎng)的普及都會帶來一定的阻礙。
所以Unicode字符集被發(fā)明了二汛,Unicode又稱為萬國碼婿崭,可以表示世界上各個國家的字符。但是Unicode只是定義了每個字符用什么數(shù)字表示肴颊,屬于計算機(jī)編碼模型中的第一層編碼氓栈,在實(shí)際的存儲和傳輸過程中,我們并不使用Unicode作為字符的編碼婿着,而一般是采用UTF-8編碼授瘦,Unicode的一種實(shí)現(xiàn)方式。
UTF-8編碼
UTF-8與Unicode有什么關(guān)系呢祟身?
UTF奥务,全稱“Unicode Transformation Formats”。是Unicode的編碼格式袜硫。UTF-8是變長編碼,以一個字節(jié)為單位對Unicode字符進(jìn)行編碼挡篓。英文等ASCII碼表中出現(xiàn)的字符用UTF-8表示的時候婉陷,仍然只會使用一個字節(jié),所以在傳輸英文的時候官研,使用UTF-8會節(jié)省很多空間秽澳。
我們看看Unicode編碼是如何轉(zhuǎn)化為UTF-8編碼的:
Unicode編碼(十六進(jìn)制) | UTF-8 字節(jié)流(二進(jìn)制) |
---|---|
00000000 - 0000007F | 0xxxxxxx |
00000080 - 000007FF | 110xxxxx 10xxxxxx |
00000800 - 0000FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
00010000 - 001FFFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
00200000 - 03FFFFFF | 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
04000000 - 7FFFFFFF | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
“中國”兩個漢字的Unicode編碼為:4E2D 和 56FD。
“中國”兩個漢字的UTF-8編碼為:E4B8AD 和 E59BBD戏羽。
以“中”為例担神,UTF-8編碼轉(zhuǎn)化為二進(jìn)制是:
1110 0100
10 111000
10 101101
去掉每個字節(jié)的頭部,剩下的二進(jìn)制串為 0100 1110 0010 1101始花,轉(zhuǎn)化為16進(jìn)制為4E 2D妄讯,正好是“中”的Unicode編碼孩锡。
Unicode字符有幾個字節(jié)
經(jīng)常會困惑一個問題,Unicode字符占用幾個字節(jié)亥贸?
Unicode字符一開始被發(fā)明的時候躬窜,只有兩個字節(jié)(也就是UCS-2),但是到后面發(fā)現(xiàn)有一些漢字(比較冷僻的)炕置,Unicode的碼點(diǎn)已經(jīng)用完荣挨,無法表示了。后面ISO對Unicode編碼進(jìn)行了擴(kuò)展(也就是UCS-4)朴摊,用四個字節(jié)表示一個字符默垄,這樣就完全夠用了。
- UTF-8屬于變長編碼甚纲,最大長度是6個字節(jié)口锭, UTF-8的4個字節(jié),可以表示0x10000-0x001FFFFF的Unicode(最多21位)贩疙。
4個字節(jié)以內(nèi)讹弯,已經(jīng)包含了Unicode所有字符。
5这溅、6個字節(jié)表示的已經(jīng)是非Unicode編碼范圍组民,屬于UCS-4 編碼。早期UTF-8規(guī)范也可以達(dá)到6字節(jié)序列悲靴,不過2003年11月UTF-8 被 RFC 3629 重新規(guī)范臭胜,只能使用原來Unicode定義的區(qū)域, U+0000到U+10FFFF癞尚。根據(jù)規(guī)范耸三,這些字節(jié)值將無法出現(xiàn)在合法 UTF-8序列中。 - UTF-16屬于變長編碼浇揩,UTF-16是完全對應(yīng)于UCS-2的仪壮,但是它通過一種代理機(jī)制(感興趣可以自己去看看),用兩個UTF-16碼元也可以表示UCS-4字符集里面的字符胳徽。
- UTF-32屬于定長編碼积锅,UTF-32是完全對應(yīng)于UCS-4的
所以,Unicode到底用幾個字節(jié)表示养盗,取決于我們使用了它的哪種實(shí)現(xiàn)方式是(在選擇文件的編碼時缚陷,沒有Unicode這個選項(xiàng)),是UTF-8往核,UTF-16箫爷,還是UTF-32。我們文件采用的編碼方式是UTF-32,則Unicode是4個字節(jié)虎锚。