日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

萬字長文講解編碼知識,看這文就夠了!| 原力計劃

作者 | Aledsan

責編 | 王曉曼

出品 | CSDN博客

萬字長文講解編碼知識,看這文就夠了!| 原力計劃

基礎概念

1、字符

字符指類字形單位或符號,包括字母、數字、運算符號、標點符號和其他符號,以及一些功能性符號。一般來說我們稱某個字符集里面的字符,叫xx字符,如ASCII字符集里面的ASCII字符,GB2312字符集里面的GB2312字符。

2、字符集

字符集(Character Set、Charset),字面上的理解就是字符的集合,是一個自然語言文字系統支持的所有字符的集合。字符是各種文字和符號的總稱,包括文字、數字、字母、音節、標點符號、圖形符號等。例如ASCII字符集,定義了128個字符;GB2312字符集定義了7445個字符。而字符集準確地來說,指的是已編號的字符的有序集合(但不一定是連續的,后文有詳細介紹)。

常見字符集名稱:ASCII字符集、GB2312字符集、BIG5字符集、 GB18030字符集、Unicode字符集等。

3、碼位

在字符編碼術語中,碼位(code point)或稱編碼位置、碼點,是組成碼空間(或代碼頁)的數值。例如,ASCII碼包含128個碼位,范圍是016進制到7F16進制,擴展ASCII碼包含256個碼位,范圍是016進制到FF16進制,而Unicode包含1,114,112個碼位,范圍是016進制到10FFFF16進制。Unicode碼空間劃分為17個Unicode字符平面(基本多文種平面,16個輔助平面),每個平面有65,536(= 216)個碼位。因此Unicode碼空間總計是17 × 65,536 = 1,114,112. —解釋來源于維基百科。

4、字符編碼

字符編碼(Character Encoding),是把字符集中的字符按一定方式編碼為某指定集合中的某一對象的過程(比如將字符編碼為由0和1兩個數字所組成的位串模式、由0~9十個數字所組成的自然數序列或電脈沖等),亦即在字符集與指定集合兩者之間建立一個對應關系(即映射關系)的過程。這是信息處理的一項基礎技術。常見的例子包括將拉丁字母表編碼成摩斯電碼和ASCII碼。

PS:這里我們計算機這里字符編碼肯定是用二進制來編碼的。

看完這四個概念,你應該要明白,它們之間的關系,以ASCII為例,下圖解釋它們之間關系。

萬字長文講解編碼知識,看這文就夠了!| 原力計劃

這里細說一下,碼位就是這個字符集里面字符的一個表示位置,通俗來說,碼位就是一般跟字符集綁在一起,字符編碼是把字符集中的字符編碼為特定的二進制數,以便在計算機中存儲。這個二進制數就叫xx碼。

萬字長文講解編碼知識,看這文就夠了!| 原力計劃

字符集編碼分類總結

在說字符集編碼之前,先明確一個觀點,字符集編碼與字符集是兩個不同層面的概念:

(1)charset 是character set 的簡寫,即字符集。

(2)encoding 是 charsetencoding 的簡寫,即字符集編碼,簡稱編碼。

萬字長文講解編碼知識,看這文就夠了!| 原力計劃

1、ASCII編碼

ASCII(美國信息交換標準代碼)是基于拉丁字母(就是我們現在的英文字母)的一套電腦編碼系統。它主要用于顯示現代英語,而其擴展版本延伸美國標準信息交換碼則可以部分支持其他西歐語言,并等同于國際標準ISO/IEC 646

ASCII由電報碼發展而來。第一版標準發布于1963年,1967年經歷了一次主要修訂,最后一次更新則是在1986年,至今為止共定義了128個字符;其中33個字符無法顯示(一些終端提供了擴展,使得這些字符可顯示為諸如笑臉、撲克牌花式等8-bit符號),且這33個字符多數都已是陳廢的控制字符。控制字符的用途主要是用來操控已經處理過的文字。在33個字符之外的是95個可顯示的字符。用鍵盤敲下空白鍵所產生的空白字符也算1個可顯示字符(顯示為空白)。

每個ASCII字符占用1個字節(8bits),共有128位字符或符號,使用7位二進制數(剩下的1位二進制為0,即高位為0)來表示所有的大寫和小寫字母,數字0 到9、標點符號,以及在美式英語中使用的特殊控制字符。

缺點:ASCII的最大缺點是只能顯示26個基本拉丁字母、阿拉伯數目字和英式標點符號,因此只能用于顯示現代美國英語(而且在處理英語當中的外來詞如naïve、café、élite等等時,所有重音符號都不得不去掉,即使這樣做會違反拼寫規則)。而EASCII(即擴展的ASCII碼,利用8位的高位設為1進行擴展)雖然解決了部分西歐語言的顯示問題,但對更多其他語言依然無能為力。因此現在的操作系統內碼(稍后會講)基本已經拋棄ASCII碼而轉用Unicode碼。

ASCII碼表 :http://www.asciitable.com

2、GB2312編碼

前面可以看到ASCII碼即使進行了擴展也能表示的字符也很少,尤其是當需要計算機顯示存儲中文的時候,就需要一種對中文進行編碼的字符集,GB 2312就是解決中文編碼的字符集,由國家標準委員會發布。那個時候當中國人們得到計算機時,已經沒有可以利用的字節狀態來表示漢字,況且有6000多個常用漢字需要保存,于是想到把那些ASCII碼中127號之后的奇異符號們直接取消掉, 規定:一個小于127的字符的意義與原來相同,但兩個大于127的字符連在一起時,就表示一個漢字,前面的一個字節(稱之為高字節)從0xA1用到0xF7,后面一個字節(低字節)從0xA1到0xFE,這樣我們就可以組合出大約7000多個簡體漢字了。在這些編碼里,我們還把數學符號、羅馬希臘的字母、日文的假名們都編進去了,連在 ASCII 里本來就有的數字、標點、字母都統統重新編了兩個字節長的編碼,這就是常說的"全角"字符,而原來在127號以下的那些就叫"半角"字符了。這種漢字方案叫做 “GB2312”。GB2312 是對ASCII 的中文擴展。兼容ASCII。

萬字長文講解編碼知識,看這文就夠了!| 原力計劃

這里的A GB2312碼是0xA3C1,0xA3和0xC1都是高于127的,所以判斷它是個全角字符,另外我們可以觀察到所有的GB2312編碼表中的GB2312碼每個字節都是大于0xA0的,這個就是為了保證能區分是否為ASCII碼,小于127的字節就按照ASCII碼標準,碰到連續兩個大于127字節就組合成一個GB2312碼。

GB2312漢字編碼字符集對照表:
http://tools.jb51.net/table/gb2312

3、GBK編碼

但是中國的漢字太多了,我們很快就就發現有許多人的人名沒有辦法在這里打出來,不得不繼續把 GB2312 沒有用到的碼位找出來用上。后來還是不夠用,于是干脆不再要求低字節一定是127號之后的內碼,只要第一個字節是大于127就固定表示這是一個漢字的開始,不管后面跟的是不是擴展字符集里的內容。結果擴展之后的編碼方案被稱為 “GBK” 標準,GBK 包括了GB2312 的所有內容,同時又增加了近20000個新的漢字(包括繁體字)和符號

4、GB18030編碼

后來中國的少數民族也要用電腦了,GBK的兩萬多字也已經無法滿足我們的需求了,還有更多可能你自己從來沒見過的漢字需要編碼。這時候顯然只用2bytes表示一個字已經不夠用了(2byte最多只有65536種組合,然而為了和ASCII兼容,最高位不能為0就已經直接淘汰了一半的組合,只剩下3萬多種組合無法滿足全部漢字要求)。因此GB18030多出來的漢字使用4byte編碼。

當然,為了兼容GBK,這個四字節的前兩位顯然不能與GBK沖突(實操中發現后兩位也并沒有和GBK沖突)。通過多年的發展至此,GB18030編碼的中文文件已經有七萬多個漢字了。

GB18030包含三種長度的編碼:單字節的ASCII、雙字節的GBK(略帶擴展)、以及用于填補所有Unicode碼位的四字節UTF區塊。所以我們說GB18030采用多字節編碼,每個字符可以由 1 個、2 個或 4 個字節組成

其實我們用到的99%以上的漢字,都在GB2312那一塊區域內。在實際使用中,GBK編碼已經可以滿足大部分場景了,GB18030編碼中所有漢字都是我們這輩子都不一定能見到的文字,所以平時經常會使用的就是GBK編碼。

這里額外總結一下這四個兼容性關系是GB18030兼容GBK,GBK兼容GB2312,GB2312兼容ASCII。所謂兼容,你可以簡單理解為子集、不沖突的關系。

例如GB2312編碼的文件中可以出現ASCII字符,GBK編碼的文件中可以出現GB2312和ASCII字符,GB18030編碼的文件可以出現GBK、GB2312、ASCII字符。

5、Unicode

友情建議:看Unicode一些概念解釋和歷史時,建議看維基百科,而且是英文版的,別用中文版,有些地方講的模棱兩可,容易陷入盲區。

Unicode(中文:萬國碼、國際碼、統一碼、單一碼)(全稱Universal Multiple-Octet Coded Character Set)它伴隨著通用字符集(英語:Universal Character Set, UCS)的標準而發展。所以可以看出他是字符集。

(1)Unicode與 ISO 10646

全世界很多個國家都在為自己的文字編碼,并且互不相通,不同的語言字符編碼值相同卻代表不同的符號(例如:韓文編碼EUC-KR中“???”的編碼值正好是漢字編碼GBK中的“茄憊絹”)。

因此,同一份文檔,拷貝至不同語言的機器,就可能成了亂碼,于是人們就想:我們能不能定義一個超大的字符集,它可以容納全世界所有的文字字符,再對它們統一進行編碼,讓每一個字符都對應一個不同的編碼值,從而就不會再有亂碼了

如果說“各個國家都在為自己文字獨立編碼”是百家爭鳴,那么“建立世界統一的字符編碼”則是一統江湖,誰都想來做這個武林盟主。早前就有兩個機構做了這個事:

  • 國際標準化組織(ISO),他們于1984年創建ISO/IEC JTC1/SC2/WG2工作組,試圖制定一份“通用字符集”(Universal Character Set,簡稱UCS),并最終制定了ISO 10646標準。(簡單來說ISO 10646標準就是UCS)

  • 統一碼聯盟,他們由Xerox、Apple等軟件制造商于1988年組成,并且開發了Unicode標準(The Unicode Standard,這個前綴Uni很牛逼哦—Unique, Universal, and Uniform)。

Unicode與ISO 10646標準的風風雨雨:

在1984年,喜歡以繁多的編號糊弄群眾的國際標準化組織ISO也開始著手制定解決不同語言字符數量太大問題的解決方案,這一方案被稱為Universal Character Set(UCS),正式的編號是ISO-10646(記得么,ASCII是ISO-646,不知這種安排是否是故意的)。

還是ISO高瞻遠矚,一開始就確定了UCS是一個31位的編碼字符集(即用一個大小不超過2的31次方的整數數字為每個字符編號),這回真的足以容納古往今來所有國家,所有語言所包含的字符了(是的,任何國家,任何小語種都包括)。雖然后來他們意識到,2的31次方個碼位又實在太多了……

天下大勢,分久必合。無論Unicode還是UCS,最初的目的都是杜絕各種各樣名目繁多形式各異互不兼容老死不相往來的私用擴展編碼(好啰嗦的一句話),結果兩方確立標準的同時(最初時這兩個標準是不兼容的),因為都是個干個的,肯定不可能一模一樣,出現標準不同。

1991年,Unicode聯盟與ISO的工作組終于開始討論Unicode與UCS的合并問題,雖然其后的合并進行了很多年,Unicode初版規范中的很多編碼都需要被改寫,UCS也需要對碼空間的使用進行必要限制,但成果是喜人的。

最終,兩者統一了抽象字符集(即任何一個在Unicode中存在的字符,在UCS中也存在),且最靠前的65535個字符也統一了字符的編碼。對于碼空間,兩者同意以一百一十萬為限(即兩者都認為雖然65536不夠,但2的31次方又太大,一百一十萬是個雙方都可接受的碼空間大小,也夠用,當然,這里說的一百一十萬只是個約數),Unicode將碼空間擴展到了一百一十萬,而UCS將永久性的不使用一百一十萬以后的碼位。

也就是說,現在再講Unicode只包含65536個字符是不對的(雖然大家現在都知道Unicode至少都可以囊括幾億個字符)。除了對已經定義的字符進行統一外,Unicode聯盟與ISO工作組也同意今后任何的擴展工作兩者均保持同步,因此雖然從歷史的意義上講Unicode與UCS不是一回事(甚至細節上說也不是一回事),但現在提起Unicode,指代兩者均無不妥,畢竟因為已經統一了。

(現在網上基本上把Unicode字符集叫做UCS,Unicoide的全稱是 Universal Multiple-Octet Coded Character Set簡寫也是UCS,一看也對上了,害,只能說天注定)。

現在Unicode編碼點分為17個平面(plane),每個平面包含216(即65536)個碼位(codepoint)。17個平面的碼位可表示為從U+xx0000到U+xxFFFF,其中xx表示十六進制值從0016到1016,共計17個平面。

這第一個位置(當xx是00的時候)被稱為BMP(基本多文種平面,BasicMultilingualPlane)。它包含了最常用的碼位從U+0000到U+FFFF(常見的65536個字符)。

其余16個平面(從下面的1號平面到16號平面),你可以叫做非BMP,由此這樣分的話里面的字符就有兩個概念:BMP字符和非BMP字符,后者也被稱為補充字符。(偷偷告訴你們,大家喜聞樂見的Emoji表情都是在1號平面,范圍是U+1F600-U+1F64F)

萬字長文講解編碼知識,看這文就夠了!| 原力計劃

(2)UCS-2和UCS-4

ISO10646標準為“通用字符集”(UCS)定義了一種16位的編碼形式(即UCS-2)UCS-2全稱Universal Character Set coded in 2octets,從英文上就可以看出含義,以2字節編碼的通用字符集編碼,固定占用2個字節,它包含65536個編碼空間(可以為全世界最常用的63K字符編碼,為了兼容Unicode,0xD800-0xDFFF之間的碼位未使用)。

例:“漢”的UCS-2編碼為6C49。除此之外ISO10646標準為“通用字符集”(UCS)還定義了一種31位的編碼形式(即UCS-4),UCS-4全稱UniversalCharacter Set coded in 4 octets,其編碼固定占用4個字節,編碼空間為0x00000000 ~0x7FFFFFFF(可以編碼20多億個字符)。

隨著Unicode與ISO 10646合并統一,Unicode就用UCS通用字符集標準,早期的 Unicode 編碼實現也就采用了UCS-2和UCS-4。(準確來說是UCS-2,UCS-4基本上是理論,沒付諸實際,畢竟早期65536個字符已經夠用了,我兩個字節編碼能實現的事,腦子笨的人才會用四個字節實現,你以為存儲和帶寬有多的)。

萬字長文講解編碼知識,看這文就夠了!| 原力計劃

這里編碼最多也就存在UCS-2(big Endian和LittleEndian先不管,后面會講)。

Unicode字符集只規定了碼點和文字之間的對應關系,并沒有規定碼點在計算機中如何存儲。UCS-2和UCS-4就規定了具體的實現,后來改進演變為了UTF-16, UTF-32。然后又創造了一種全新的簡單粗暴好用的變長編碼UTF-8,于是乎這三哥們就形成了現代Unicode字符集編碼實現的三劍客。

(3)UTF-16與UTF-32

Unicode與ISO 10646合并統一后,Unicode與 ISO 10646 的通用字符集概念(UCS)相對應。早期實現Unicode用的編碼是UCS-2,后來隨著發展發現 216(即65536)個字符不能滿足了,Unicode標準本身發生了變化:65536個字符顯得不足,引入了更大的31位空間和一個編碼(UCS-4),每個字符需要4個字節。

但是統一碼聯盟對此予以抵制(這就是為什么我之前說UCS-4是一種理論編碼,根本就沒付諸實際),這是因為每個字符4個字節浪費了很多磁盤空間和內存,并且因為一些制造商已經在每個字符2個字節的技術上投入了大量資金。所以最后通過一系列巴拉巴拉討論規定形成了一種折衷方案,建立了UTF-16編碼方案(此時Unicode標準2.0),它替代了原有的UCS-2,并做了改進。

它與UCS-2一樣,它使用兩個字節為全世界最常用的63K字符編碼,不同的是,它使用4個字節對不常用的字符進行編碼。目的就是為了支持從17個平面編碼1,112,064個代碼點。

UTF-16屬于變長編碼。我們可以將UTF-16編碼看成是UCS-2編碼父集。在沒有輔助平面字符(surrogate code points)前,UTF-16與UCS-2所指的是同一意思。但當引入輔助平面字符后,就稱為UTF-16了。

現在應該認為UCS-2已作廢,如果有人還用這種,也不必糾結,它就是表達用定長2字節編碼,自己心里清楚就行(基本上你查維基百科上UCS-2都是重定向到UTF-16)。

另外當時ISO 10646的UCS-4編碼并入了Unicode標準,而UCS-4有20多億個編碼空間,但實際使用范圍并不超過0x10FFFF,并且為了兼容Unicode標準,ISO也承諾將不會為超出0x10FFFF的UCS-4編碼賦值。

由此提出了實實在在的UTF-32編碼(現在也應該認為UCS-4像UCS-2一樣作廢,維基百科上UCS-4也重定向到UTF-32頁面),它的編碼值與UCS-4相同,只不過其編碼空間被限定在了0~0x10FFFF之間。因此也可以說:UTF-32是UCS-4的一個子集。

(現在若有軟件聲稱自己支持UCS-2,那其實是暗指它不能支持在UTF-16中超過2字節的字集。)

UTF-16(16 位 Unicode轉換格式)是一種字符編碼,能夠對Unicode的所有1,112,064個有效碼點進行編碼(實際上,此代碼點數由UTF-16的設計決定,這個你細品你就知道什么意思,就好像某個班有55個人,根據55個座位確定55個人,而55個座位這個多少是由55個人決定的,兩者是相互的,這是一個哲學道理,hh扯遠了,所以其中意味自行明白)。

前面提到過:Unicode編碼點分為17個平面(plane),每個平面包含216(即65536)個碼位(codepoint),而第一個平面稱為“基本多語言平面”(Basic Multilingual Plane,簡稱BMP),其余平面稱為“輔助平面”(Supplementary Planes)。其中“基本多語言平面”(00xFFFF)中0xD8000xDFFF之間的碼位作為保留,未使用。

UCS-2只能編碼“基本多語言平面”中的字符,此時UTF-16與UCS-2的編碼一樣(都直接使用Unicode的碼位作為編碼值),例:“漢”在Unicode中的碼位為6C49,而在UTF-16編碼也為6C49。

另外,UTF-16還可以利用保留下來的0xD800-0xDFFF區段的碼位來對“輔助平面”的字符的碼位進行編碼,因此UTF-16可以為Unicode中所有的字符編碼。

UTF-16和UTF-32也就是如今Unicode編碼的標準之二,他們的區別就是UTF-16是變長編碼,大部分是2字節和少部分4字節,UTF-32是定長編碼,表示任何字符都用 4 字節

(4)UTF-8

從前述內容可以看出:無論是UCS-2/4還是UTF-16/32,一個字符都需要多個字節來編碼,這對那些英語國家來說多浪費帶寬啊!(尤其在網速本來就不快的那個年代......),而且我們注意到UTF-16最少2字節和UTF-32不變4字節,這肯定是不兼容ASCII碼的,由此,UTF-8產生了。

在UTF-8編碼中,ASCII碼中的字符還是ASCII碼的值,只需要一個字節表示,其余的字符需要2字節、3字節或4字節來表示。

UTF-8的編碼規則:

  • 對于ASCII碼中的符號,使用單字節編碼,其編碼值與ASCII值相同。其中ASCII值的范圍為0~0x7F,所有編碼的二進制值中第一位為0(這個正好可以用來區分單字節編碼和多字節編碼)。

  • 其它字符用多個字節來編碼(假設用N個字節),多字節編碼需滿足:第一個字節的前N位都為1,第N+1位為0,后面N-1 個字節的前兩位都為10,這N個字節中其余位全部用來存儲Unicode中的碼位值。

萬字長文講解編碼知識,看這文就夠了!| 原力計劃

現如今UTF-8 是互聯網上使用最廣的一種 Unicode 的實現方式,是其他兩種無可比擬的。

(5)UTF的字節序和BOM

字節序就要先補充一點知識:

碼元(code unit):是能用于處理或交換編碼文本的最小比特組合。它代表某種編碼中最小的可用來識別一個合法字符的最小字節數序列。

  • UTF-8使用變長的字節序列來表示字符;某個字符(對應一個碼點)可能使用1-4個字節才能表示;在UTF-8中一個字符最小可能一個字節,所以我們規定1個字節就是一個碼元;

  • UTF-16使用也變長字節序列來表示字符;某個字符(對應一個碼點)可能使用2個或者4個字符來表示;因為2個字節序列是最小的能夠識別一個碼點的單位,同理我們規定2個字節就是一個碼元;

  • UTF-32使用定長的4個字節表示一個字符;一個字符(對應一個碼點)使用4個字符來表示,這樣4個字節就是一個碼元。

簡單來說,就是“碼點”經過映射后得到的二進制串的轉換格式單位稱之為“碼元”。“碼點”就是一串二進制數,“碼元”就是切分這個二進制數的方法。這些編碼每次處理一個碼元,你可以把它理解為UTF-8每次讀碼點的8位,UTF-16每次讀碼點的16位,UTF-32每次讀碼點的32位,。當然這也是為什么叫這些叫Unicode轉換格式的原因。處理的是同一個字符集,但是處理方式不同。

萬字長文講解編碼知識,看這文就夠了!| 原力計劃

字節序

UTF-8一次一個UTF-8碼元,即處理一個字節,沒有字節序的問題。UTF-16一次處理一個UTF-16碼元,對應兩個字節,UTF-32一次一個UTF-32碼元,對應處理四個字節,所以這就要考慮到一個字節序問題。

以UTF-16w為例,在解釋一個UTF-16編碼文本前,首先要弄清楚每個編碼單元的字節序。例如收到一個“奎”的Unicode編碼是594E,“乙”的Unicode編碼是4E59。

如果我們收到UTF-16字節流“594E”,那么這是“奎”還是“乙”?這就考慮大小端問題,所以UTF-16編碼包括三種:UTF-16BE(Big Endian),UTF-16LE(Little Endian)、UTF-16(類似的名稱UCS-2BE和UCS-2LE用于顯示UCS-2的版本。)

UTF-16BE和UTF-16LE好理解,直接指定了字節序(大小端),但是UTF-16怎么處理呢?

Unicode規范中推薦的標記字節順序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte Order Mark。BOM是一個有點小聰明的想法:

在UCS編碼中有一個叫做"ZERO WIDTH NO-BREAKSPACE"的字符,它的編碼是FEFF。而FFFE在UCS中是不存在的字符,所以不應該出現在實際傳輸中。UCS規范建議我們在傳輸字節流前,先傳輸字符"ZERO WIDTH NO-BREAK SPACE"。這樣如果接收者收到FEFF,就表明這個字節流是Big-Endian的;如果收到FFFE,就表明這個字節流是Little-Endian的

同樣的類比,UTF-32也是這樣的。有UTF-32BE、UTF-32LE、UTF-32。前面UTF-32BE和UTF-32LE直接指定了字節序(大小端),后面的UTF-32也是靠BOM。

UTF-8不需要BOM來表明字節順序,但可以用BOM來表明編碼方式。字符"ZERO WIDTH NO-BREAKSPACE"的UTF-8編碼是EF BB BF(讀者可以用我們前面介紹的編碼方法驗證一下)。所以如果接收者收到以EF BB BF開頭的字節流,就知道這是UTF-8編碼了。

windows就是使用BOM來標記文本文件的編碼方式的。它就建議所有的 Unicode 文件應該以 ZERO WIDTH NOBREAK SPACE(U+FEFF)字符開頭。這作為一個“特征符”或“字節順序標記(byte-ordermark,BOM)”來識別文件中使用的編碼和字節順序。所以用Windows自帶的記事本將文件保存為UTF-8編碼的時候,記事本會自動在文件開頭插入BOM(雖然BOM對UTF-8來說并不是必須的)。

但也有一些系統或程序不支持BOM,因此帶有BOM的Unicode文件有時會帶來一些問題。比如JDK1.5以及之前的Reader都不能處理帶有BOM的UTF-8編碼的文件,解析這種格式的xml文件時,會拋出異常:Content is not allowed inprolog。

linux/UNIX 并沒有使用 BOM,因為它會破壞現有的 ASCII 文件的語法約定。所以一般我們不建議用Windows自帶的記事本編輯UTF-8文件就是這樣。

萬字長文講解編碼知識,看這文就夠了!| 原力計劃

總結

1、簡單地說:Unicode和UCS是字符集,不屬于編碼UTF-8、UTF-16、UTF-32等是針對Unicode字符集的編碼,UCS-2和UCS-4是針對UCS字符集的編碼(只是我們習慣把Unicode字符集編碼簡稱為Unicode編碼,把UCS字符集編碼稱為UCS編碼)。

Unicode沿用UCS字符集,在UCS-2和UCS-4基礎上提出的UTF-16、UTF-32。并發展了UTF-8,發展到現在,就密不可分了,大家基于UCS就把Uniocde維護好就行,發布標準大家統一。以往的UCS-2和UCS-4概念就默認作廢了這樣一個關系,整個他們的發展長話短說就是這樣,懂了嗎。

2、UTF-8、UTF-16、UTF-32、UCS-2、UCS-4對比:

萬字長文講解編碼知識,看這文就夠了!| 原力計劃

由于歷史方面的原因,你還會在不少地方看到把Unicode稱為一種編碼的情況,那是因為早期的2字節編碼最初稱為“ Unicode”但現在稱為“ UCS-2”,這種情況下的 Unicode 通常就是 UTF-16 或者是更早的 UCS-2 編碼,只是被一直搞混了,在某些老軟件上尤為常見。比如下面editplus里面文件編碼設置。

萬字長文講解編碼知識,看這文就夠了!| 原力計劃

以前的Windows電腦上的記事本(左邊)顯示的是Unicode,不過現在好像改了變成了UTF-16。

萬字長文講解編碼知識,看這文就夠了!| 原力計劃

不過由于各種原因,必須承認,在不同的語境下,“Unicode”這個詞有著不同的含義。

它可能指:

(1)Unicode 標準

(2)Unicode 字符集

(3)Unicode 的抽象編碼(編號),也即碼點、碼位(code point)

(4)Unicode 的一個具體編碼實現,通常即為變長的 UTF-16(16 或 32 位),又或者是更早期的定長 16 位的 UCS-2

所以像我一般有時候非要區分的話都是直接說全,Unicode 標準,Unicode 字符集,Unicode編碼等等。

萬字長文講解編碼知識,看這文就夠了!| 原力計劃

ANSI編碼

為使計算機支持更多語言,通常使用0x800~xFF范圍的2個字節來表示1個字符。比如:漢字‘中’ 在中文操作系統中,使用 [0xD6,0xD0]這兩個字節存儲。

不同的國家和地區制定了不同的標準,由此產生了 GB2312、GBK、GB18030、Big5、Shift_JIS 等各自的編碼標準。這些使用多個字節來代表一個字符的各種語言延伸編碼方式,稱為 ANSI 編碼。

在簡體中文Windows操作系統中,ANSI 編碼代表 GBK 編碼;在繁體中文Windows操作系統中,ANSI編碼代表Big5;在日文Windows操作系統中,ANSI 編碼代表 Shift_JIS 編碼。

不同 ANSI 編碼之間互不兼容,當信息在國際間交流時,無法將屬于兩種語言的文字,存儲在同一段 ANSI 編碼的文本中。

在使用ANSI編碼支持多語言階段,每個字符使用一個字節或多個字節來表示(MBCS,Multi-Byte Character System),因此,這種方式存放的字符也被稱作多字節字符。比如,“中文123” 在中文 Windows 95 內存中為7個字節,每個漢字占2個字節,每個英文和數字字符占1個字節。

在非 Unicode 環境下,由于不同國家和地區采用的字符集不一致,很可能出現無法正常顯示所有字符的情況。微軟公司使用了代碼頁(Codepage)轉換表的技術來過渡性的部分解決這一問題,即通過指定的轉換表將非Unicode 的字符編碼轉換為同一字符對應的系統內部使用的Unicode 編碼。

可以在“語言與區域設置”中選擇一個代碼頁作為非 Unicode 編碼所采用的默認編碼方式,如936為簡體中文GBK,950為正體中文Big5(皆指PC上使用的)。在這種情況下,一些非英語的歐洲語言編寫的軟件和文檔很可能出現亂碼。而將代碼頁設置為相應語言中文處理又會出現問題,這一情況無法避免。

從根本上說,完全采用統一編碼才是解決之道,雖然現在Unicode有了,但由于歷史遺留,老軟件等等原因,所以系統統一用某種編碼格式的Unicode目前尚無法做到這一點。

代碼頁技術現在廣泛為各種平臺所采用。UTF-7 的代碼頁是65000,UTF-8的代碼頁是65001。簡體中文上使用的代碼頁為936,GBK編碼。

以前中文DOS、中文/日文Windows95/98時代系統內碼使用的是ANSI編碼(本地化,根據不同地區設置不同的系統內碼Windows版本),現在win7,win10等等系統的內碼都是用的Unicode。

不過微軟為了以前的程序兼容性,比如在某些情況下,比如你的程序需要和不支持Unicode的程序交互時,可能還是會需要用到code page,提供代碼頁服務(就好比微軟不能說:“老子支持unicode了,以后不支持Unicode的程序都給我滾粗。”只能撅著屁股讓這些老掉牙的程序仍然可以運行,于是只好給他們提供一個“非Unicode默認字符集”) 。可以在cmd下輸入chcp查看code page。

萬字長文講解編碼知識,看這文就夠了!| 原力計劃
  • WindowsAPI 的Wide Char 表達是 UTF-16: Unicode (Windows), L"" 表示是轉換為 wide char。

  • Cocoa的NSString 和 Core Foundation 的CFString 內部表達都是 UTF-16,所以其實 OSX 和 IOS 內部處理都用的是 UTF-16。

  • JAVAString 的內部表達是 UTF-16,所以大量跨平臺程序和 Android 程序其實內部也在用 UTF-16。

  • 大部分的操作系統和 UI framework 的內部字符串表達(內碼)都是UTF-16,不過Linux系統內使用的內碼是UTF-8。

萬字長文講解編碼知識,看這文就夠了!| 原力計劃

Tip:內碼和外碼

在計算機科學及相關領域當中,內碼指的是“將信息編碼后,透過某種方式存儲在特定記憶設備時,設備內部的編碼形式”。在不同的系統中,會有不同的內碼。

在以往的英文系統中,內碼為ASCII。在繁體中文系統中,當前常用的內碼為大五碼。在簡體中文系統中,內碼則為國標碼。

為了軟件開發方便,如國際化與本地化,現在許多系統會使用Unicode做為內碼,常見的操作系統Windows、mac OS X、Linux皆如此。許多編程語言也采用Unicode為內碼,如Java、Python3。

外碼:除了內碼,皆是外碼。要注意的是,源代碼編譯產生的目標代碼文件(如果Java可執行文件或class文件)中的編碼方式屬于外碼。

引用文章:

1、必讀,真說清的話得結合上面的維基百科上的說法理解:

https://en.wikipedia.org/wiki/Universal_Coded_Character_Set

https://en.wikipedia.org/wiki/Unicode

https://en.wikipedia.org/wiki/UTF-16

https://en.wikipedia.org/wiki/UTF-32

2、除此之外參考引用了下面三篇文章的一些觀點:

http://www.blogjava.net/zhenandaci/archive/2008/12/24/248014.html

https://www.cnblogs.com/malecrab/p/5300503.html

https://blog.51cto.com/polaris/377468

版權聲明:本文為CSDN博主「Aledsan」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。

原文鏈接:
https://blog.csdn.net/weixin_43465312/article/details/105918985

分享到:
標簽:編碼
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定