青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

 

字符編碼詳解——徹底理解掌握編碼知識(shí),“亂碼”不復(fù)存在

摘自 <http://polaris1119.iteye.com/blog/739410> 每 一個(gè)程序員都不可避免的遇到字符編碼的問題,特別是做Web開發(fā)的程序員,“亂碼問題”一直是讓人頭疼的問題,也許您已經(jīng)很少遇到“亂碼”問題,然而,對(duì) 解決亂碼的方法的內(nèi)在原理,您是否明白?本人作為一個(gè)程序員,在字符編碼方面同樣遇到不少問題,而且一直對(duì)各種編碼懵懵懂懂、不清不楚;在工作中也曾經(jīng)遇 到一個(gè)很煩人的編碼問題。這兩天在網(wǎng)上收集了大量編碼方面的資料,對(duì)字符編碼算是理解的比較清楚了。下面把我認(rèn)為比較重要的知識(shí)點(diǎn)記錄下來,一方面方便以 后復(fù)習(xí);另一方面也希望給跟我一樣懵懵懂懂的人一個(gè)參考。不對(duì)或不妥之處,請(qǐng)批評(píng)指正。

在此之前,先了解一些有用概念:“字符集”、“字符編碼”和“內(nèi)碼”。

1、字符集與字符編碼

字符是各種文字和符號(hào)的總稱,包括各個(gè)國家文字、標(biāo)點(diǎn)符號(hào)、圖形符號(hào)、數(shù)字等。字符集是多個(gè)字符的集合,字符集種類較多,每個(gè)字符集包含的字符 個(gè)數(shù)不同,常見字符集有:ASCII字符集、ISO 8859字符集、GB2312字符集、BIG5字符集、GB18030字符集、Unicode字符集等。計(jì)算機(jī)要準(zhǔn)確的處理各種字符集文字,需要進(jìn)行字符 編碼,以便計(jì)算機(jī)能夠識(shí)別和存儲(chǔ)各種文字。?

編碼(encoding)和字符集不同。字符集只是字符的集合,不一定適合作網(wǎng)絡(luò)傳送、處理,有時(shí)須經(jīng)編碼(encode)后才能應(yīng)用。如Unicode可依不同需要以UTF-8、UTF-16、UTF-32等方式編碼。

字符編碼就是以二進(jìn)制的數(shù)字來對(duì)應(yīng)字符集的字符。

因此,對(duì)字符進(jìn)行編碼,是信息交流的技術(shù)基礎(chǔ)。

使用哪些字符。也就是說哪些漢字,字母和符號(hào)會(huì)被收入標(biāo)準(zhǔn)中。所包含“字符”的集合就叫做“字符集”。
規(guī)定每個(gè)“字符”分別用一個(gè)字節(jié)還是多個(gè)字節(jié)存儲(chǔ),用哪些字節(jié)來存儲(chǔ),這個(gè)規(guī)定就叫做“編碼”。

各個(gè)國家和地區(qū)在制定編碼標(biāo)準(zhǔn)的時(shí)候,“字符的集合”和“編碼”一般都是同時(shí)制定的。因此,平常我們所說的“字符集”,比如:GB2312, GBK, JIS 等,除了有“字符的集合”這層含義外,同時(shí)也包含了“編碼”的含義。

注意:Unicode字符集有多種編碼方式,如UTF-8、UTF-16等;ASCII只有一種;大多數(shù)MBCS(包括GB2312)也只有一種。

2、什么是內(nèi)碼?

2.1 維基百科的解釋

在計(jì)算機(jī)科學(xué)及相關(guān)領(lǐng)域當(dāng)中,內(nèi)碼指的是“將資訊編碼后,透過某種方式儲(chǔ)存在特定記憶裝置時(shí),裝置內(nèi)部的編碼形式”。在不同的系統(tǒng)中,會(huì)有不同的內(nèi)碼。
在以往的英文系統(tǒng)中,內(nèi)碼為ASCII。在繁體中文系統(tǒng)中,目前常用的內(nèi)碼為大五碼(Big5)。在簡(jiǎn)體中文系統(tǒng)中,內(nèi)碼則為國標(biāo)碼(國家標(biāo)準(zhǔn)代碼:現(xiàn)在強(qiáng)制要求使用GB18030標(biāo)準(zhǔn);較舊計(jì)算機(jī)仍然使用GB2312)。而統(tǒng)一碼(Unicode)則為另一常見內(nèi)碼。

2.2 百度百科的解釋

內(nèi)碼是指整機(jī)系統(tǒng)中使用的二進(jìn)制字符編碼,是溝通輸入、輸出與系統(tǒng)平臺(tái)之間的交換碼,通過內(nèi)碼可以達(dá)到通用和高效率傳輸文本的目的。比如MS Word中所存儲(chǔ)和調(diào)用的就是內(nèi)碼而非圖形文字。英文ASCII字符采用一個(gè)字節(jié)的內(nèi)碼表示,中文字符如國標(biāo)字符集中,GB2312、GB12345、 GB13000皆用雙字節(jié)內(nèi)碼,GB18030(27,533漢字)雙字節(jié)內(nèi)碼漢字為20,902個(gè),其余6,631個(gè)漢字用四字節(jié)內(nèi)碼。

3、字符編碼分類總結(jié)

下面從計(jì)算機(jī)對(duì)多國語言支持的角度來總結(jié)字符編碼。

3.1 ASCII編碼

以下來自“維基百科”:
ASCII(American Standard Code for Information Interchange,美國信息互換標(biāo)準(zhǔn)代碼)是基于拉丁字母的一套電腦編碼系統(tǒng)。它主要用于顯示現(xiàn)代英語,而其擴(kuò)展版本EASCII則可以勉強(qiáng)顯示其 他西歐語言。它是現(xiàn)今最通用的單字節(jié)編碼系統(tǒng)(但是有被UniCode追上的跡象),并等同于國際標(biāo)準(zhǔn)ISO/IEC 646。
ASCII第一次以規(guī)范標(biāo)準(zhǔn)的型態(tài)發(fā)表是在1967年,最后一次更新則是在1986年,至今為止共定義了128個(gè)字符;其中33個(gè)字符無法顯示 (這是以現(xiàn)今操作系統(tǒng)為依歸,但在DOS模式下可顯示出一些諸如笑臉、撲克牌花式等8-bit符號(hào)),且這33個(gè)字符多數(shù)都已是陳廢的控制字符。控制字符 的用途主要是用來操控已經(jīng)處理過的文字。在33個(gè)字符之外的是95個(gè)可顯示的字符,包含用鍵盤敲下空白鍵所產(chǎn)生的空白字符也算1個(gè)可顯示字符(顯示為空 白)。
ASCII表:見http://zh.wikipedia.org/zh-cn/ASCII

ASCII缺點(diǎn):
ASCII的最大缺點(diǎn)是只能顯示26個(gè)基本拉丁字母、阿拉伯?dāng)?shù)目字和英式標(biāo)點(diǎn)符號(hào),因此只能用于顯示現(xiàn)代美國英語(而且在處理英語當(dāng)中的外來詞 如na?ve、café、élite等等時(shí),所有重音符號(hào)都不得不去掉,即使這樣做會(huì)違反拼寫規(guī)則)。而EASCII雖然解決了部份西歐語言的顯示問題, 但對(duì)更多其他語言依然無能為力。因此現(xiàn)在的蘋果電腦已經(jīng)拋棄ASCII而轉(zhuǎn)用Unicode。

最早的英文DOS操作系統(tǒng)的系統(tǒng)內(nèi)碼是:ASCII。計(jì)算機(jī)這時(shí)候只支持英語,其他語言不能夠在計(jì)算機(jī)存儲(chǔ)和顯示。

在該階段,單字節(jié)字符串使用一個(gè)字節(jié)存放一個(gè)字符(SBCS,Single Byte Character System)。如:"Bob123"占6個(gè)字節(jié)。

3.2 ANSI編碼

為使計(jì)算機(jī)支持更多語言,通常使用0x800~xFF范圍的2個(gè)字節(jié)來表示1個(gè)字符。比如:漢字 '中' 在中文操作系統(tǒng)中,使用 [0xD6,0xD0]這兩個(gè)字節(jié)存儲(chǔ)。

不同的國家和地區(qū)制定了不同的標(biāo)準(zhǔn),由此產(chǎn)生了GB2312,BIG5,JIS等各自的編碼標(biāo)準(zhǔn)。這些使用2個(gè)字節(jié)來代表一個(gè)字符的各種漢字延 伸編碼方式,稱為 ANSI 編碼。在簡(jiǎn)體中文系統(tǒng)下,ANSI 編碼代表 GB2312 編碼,在日文操作系統(tǒng)下,ANSI 編碼代表 JIS 編碼。

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

中文DOS、中文/日文Windows 95/98時(shí)代系統(tǒng)內(nèi)碼使用的是ANSI編碼(本地化)

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

在非 Unicode 環(huán)境下,由于不同國家和地區(qū)采用的字符集不一致,很可能出現(xiàn)無法正常顯示所有字符的情況。微軟公司使用了代碼頁(Codepage)轉(zhuǎn)換表的技術(shù)來過渡性 的部分解決這一問題,即通過指定的轉(zhuǎn)換表將非 Unicode 的字符編碼轉(zhuǎn)換為同一字符對(duì)應(yīng)的系統(tǒng)內(nèi)部使用的 Unicode 編碼。可以在“語言與區(qū)域設(shè)置”中選擇一個(gè)代碼頁作為非 Unicode 編碼所采用的默認(rèn)編碼方式,如936為簡(jiǎn)體中文GBK,950為正體中文Big5(皆指PC上使用的)。在這種情況下,一些非英語的歐洲語言編寫的軟件和 文檔很可能出現(xiàn)亂碼。而將代碼頁設(shè)置為相應(yīng)語言中文處理又會(huì)出現(xiàn)問題,這一情況無法避免。從根本上說,完全采用統(tǒng)一編碼才是解決之道,但目前尚無法做到這 一點(diǎn)。
  代碼頁技術(shù)現(xiàn)在廣泛為各種平臺(tái)所采用。UTF-7 的代碼頁是65000,UTF-8 的代碼頁是65001。

3.3 Unicode編碼

為了使國際間信息交流更加方便,國際組織制定了 UNICODE 字符集,為各種語言中的每一個(gè)字符設(shè)定了統(tǒng)一并且唯一的數(shù)字編號(hào),以滿足跨語言、跨平臺(tái)進(jìn)行文本轉(zhuǎn)換、處理的要求。

Unicode字符集可以簡(jiǎn)寫為UCS(Unicode Character Set)。早期的unicodeUnicode標(biāo)準(zhǔn)有UCS-2、UCS-4的說法。UCS-2用兩個(gè)字節(jié)編碼,UCS-4用4個(gè)字節(jié)編碼。

在 UNICODE 被采用之后,計(jì)算機(jī)存放字符串時(shí),改為存放每個(gè)字符在 UNICODE 字符集中的序號(hào)。目前計(jì)算機(jī)一般使用 2 個(gè)字節(jié)(16 位)來存放一個(gè)序號(hào)(DBCS,Double Byte Character System),因此,這種方式存放的字符也被稱作寬字節(jié)字符。比如,字符串 "中文123" 在 Windows 2000 下,內(nèi)存中實(shí)際存放的是 5 個(gè)序號(hào),一共10個(gè)字節(jié)。

Unicode字符集包含了各種語言中使用到的所有“字符”。用來給 UNICODE 字符集編碼的標(biāo)準(zhǔn)有很多種,比如:UTF-8, UTF-7, UTF-16, UnicodeLittle, UnicodeBig 等。

4、常用編碼規(guī)則

4.1 單字節(jié)字符編碼

(1)編碼標(biāo)準(zhǔn):ISO-8859-1。
(2)說明:最簡(jiǎn)單的編碼規(guī)則,每一個(gè)字節(jié)直接作為一個(gè) UNICODE 字符。比如,[0xD6, 0xD0] 這兩個(gè)字節(jié),通過 iso-8859-1 轉(zhuǎn)化為字符串時(shí),將直接得到 [0x00D6, 0x00D0] 兩個(gè) UNICODE 字符,即 "?D"。

反之,將 UNICODE 字符串通過 iso-8859-1 轉(zhuǎn)化為字節(jié)串時(shí),只能正常轉(zhuǎn)化 0~255 范圍的字符。

4.2 ANSI編碼

(1)GB2312, BIG5, Shift_JIS, ISO-8859-2。
(2)把 UNICODE 字符串通過 ANSI 編碼轉(zhuǎn)化為“字節(jié)串”時(shí),根據(jù)各自編碼的規(guī)定,一個(gè) UNICODE 字符可能轉(zhuǎn)化成一個(gè)字節(jié)或多個(gè)字節(jié)。

反之,將字節(jié)串轉(zhuǎn)化成字符串時(shí),也可能多個(gè)字節(jié)轉(zhuǎn)化成一個(gè)字符。比如,[0xD6, 0xD0] 這兩個(gè)字節(jié),通過 GB2312 轉(zhuǎn)化為字符串時(shí),將得到 [0x4E2D] 一個(gè)字符,即 '中' 字。

“ANSI 編碼”的特點(diǎn):
(1)這些“ANSI 編碼標(biāo)準(zhǔn)”都只能處理各自語言范圍之內(nèi)的 UNICODE 字符。
(2)“UNICODE 字符”與“轉(zhuǎn)換出來的字節(jié)”之間的關(guān)系是人為規(guī)定的。

4.3 UNICODE編碼

(1)編碼標(biāo)準(zhǔn):UTF-8, UTF-16, UnicodeBig。
(2)與“ANSI 編碼”類似的,把字符串通過 UNICODE 編碼轉(zhuǎn)化成“字節(jié)串”時(shí),一個(gè) UNICODE 字符可能轉(zhuǎn)化成一個(gè)字節(jié)或多個(gè)字節(jié)。

與“ANSI 編碼”不同的是:
(1)這些“UNICODE 編碼”能夠處理所有的 UNICODE 字符。
(2)“UNICODE 字符”與“轉(zhuǎn)換出來的字節(jié)”之間是可以通過計(jì)算得到的。

我們實(shí)際上沒有必要去深究每一種編碼具體把某一個(gè)字符編碼成了哪幾個(gè)字節(jié),我們只需要知道“編碼”的概念就是把“字符”轉(zhuǎn)化成“字節(jié)”就可以 了。對(duì)于“UNICODE 編碼”,由于它們是可以通過計(jì)算得到的,因此,在特殊的場(chǎng)合,我們可以去了解某一種“UNICODE 編碼”是怎樣的規(guī)則。

5、編碼的區(qū)別

5.1 GB2312、GBK和GB18030

(1)GB2312?

當(dāng)中國人們得到計(jì)算機(jī)時(shí),已經(jīng)沒有可以利用的字節(jié)狀態(tài)來表示漢字,況且有6000多個(gè)常用漢字需要保存,于是想到把那些ASCII碼中127號(hào) 之后的奇異符號(hào)們直接取消掉, 規(guī)定:一個(gè)小于127的字符的意義與原來相同,但兩個(gè)大于127的字符連在一起時(shí),就表示一個(gè)漢字,前面的一個(gè)字節(jié)(稱之為高字節(jié))從0xA1用到 0xF7,后面一個(gè)字節(jié)(低字節(jié))從0xA1到0xFE,這樣我們就可以組合出大約7000多個(gè)簡(jiǎn)體漢字了。在這些編碼里,我們還把數(shù)學(xué)符號(hào)、羅馬希臘的 字母、日文的假名們都編進(jìn)去了,連在 ASCII 里本來就有的數(shù)字、標(biāo)點(diǎn)、字母都統(tǒng)統(tǒng)重新編了兩個(gè)字節(jié)長的編碼,這就是常說的"全角"字符,而原來在127號(hào)以下的那些就叫"半角"字符了。這種漢字方案 叫做 "GB2312"。GB2312 是對(duì) ASCII 的中文擴(kuò)展。兼容ASCII。

(2)GBK?

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

(3)GB18030?
?
后來少數(shù)民族也要用電腦了,于是我們?cè)贁U(kuò)展,又加了幾千個(gè)新的少數(shù)民族的字,GBK 擴(kuò)成了 GB18030。從此之后,中華民族的文化就可以在計(jì)算機(jī)時(shí)代中傳承了。?

中國的程序員們看到這一系列漢字編碼的標(biāo)準(zhǔn)是好的,于是通稱他們叫做 "DBCS"(Double Byte Charecter Set 雙字節(jié)字符集)。在DBCS系列標(biāo)準(zhǔn)里,最大的特點(diǎn)是兩字節(jié)長的漢字字符和一字節(jié)長的英文字符并存于同一套編碼方案里,因此他們寫的程序?yàn)榱酥С种形奶? 理,必須要注意字串里的每一個(gè)字節(jié)的值,如果這個(gè)值是大于127的,那么就認(rèn)為一個(gè)雙字節(jié)字符集里的字符出現(xiàn)了。在這種情況下,"一個(gè)漢字算兩個(gè)英文字 符!"。然而,在Unicode環(huán)境下卻并非總是如此。?

5.1 Unicode和BigEndianUnicode

這兩個(gè)指示存儲(chǔ)順序不同,如"A"的Unicode編碼為6500,而BigEndianUnicode編碼為0065。

5.2 UTF-7、UTF-8和UTF-16

在Unicode里,所有的字符被一視同仁。漢字不再使用“兩個(gè)擴(kuò)展ASCII”,而是使用“1個(gè)Unicode”,注意,現(xiàn)在的漢字是“一個(gè)字符”了,于是,拆字、統(tǒng)計(jì)字?jǐn)?shù)這些問題也就自然而然的解決了。

但是,這個(gè)世界不是理想的,不可能在一夜之間所有的系統(tǒng)都使用Unicode來處理字符,所以Unicode在誕生之日,就必須考慮一個(gè)嚴(yán)峻的問題:和ASCII字符集之間的不兼容問題。?

我們知道,ASCII字符是單個(gè)字節(jié)的,比如“A”的ASCII是65。而Unicode是雙字節(jié)的,比如“A”的Unicode是0065,這就造成了一個(gè)非常大的問題:以前處理ASCII的那套機(jī)制不能被用來處理Unicode了。

另一個(gè)更加嚴(yán)重的問題是,C語言使用'\0'作為字符串結(jié)尾,而Unicode里恰恰有很多字符都有一個(gè)字節(jié)為0,這樣一來,C語言的字符串函數(shù)將無法正常處理Unicode,除非把世界上所有用C寫的程序以及他們所用的函數(shù)庫全部換掉。

于是,比Unicode更偉大的東東誕生了,之所以說它更偉大是因?yàn)樗孶nicode不再存在于紙上,而是真實(shí)的存在于我們大家的電腦中。那就是:UTF。

UTF= UCS Transformation Format,即UCS轉(zhuǎn)換(傳輸)格式。
它是將Unicode編碼規(guī)則和計(jì)算機(jī)的實(shí)際編碼對(duì)應(yīng)起來的一個(gè)規(guī)則。現(xiàn)在流行的UTF有2種:UTF-8和UTF-16。

這兩種都是Unicode的編碼實(shí)現(xiàn)。

5.2.1 UTF-8

UCS-2編碼(16進(jìn)制) ? UTF-8 字節(jié)流(二進(jìn)制)
0000 - 007F ? ? ? ? 0xxxxxxx
0080 - 07FF ? ? ? ? 110xxxxx 10xxxxxx
0800 - FFFF ? ? ? ? 1110xxxx 10xxxxxx 10xxxxxx?

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

可見UTF-8是變長的,將Unicode編碼為00000000-0000007F的字符,用單個(gè)字節(jié)來表示; 00000080-000007FF的字符用兩個(gè)字節(jié)表示;00000800-0000FFFF的字符用3字節(jié)表示。因?yàn)槟壳盀橹筓nicode-16規(guī) 范沒有指定FFFF以上的字符,所以UTF-8最多是使用3個(gè)字節(jié)來表示一個(gè)字符。但理論上來說,UTF-8最多需要用6字節(jié)表示一個(gè)字符。?

UTF-8兼容ASCII。

5.2.2 UTF-16(標(biāo)準(zhǔn)的Unicode成為UTF-16)

UTF-16和上面提到的Unicode本身的編碼規(guī)范是一致的。

UTF-16以16位為單元對(duì)UCS進(jìn)行編碼。對(duì)于小于0x10000的UCS碼,UTF-16編碼就等于UCS碼對(duì)應(yīng)的16位無符號(hào)整數(shù)。對(duì) 于不小于0x10000的UCS碼,定義了一個(gè)算法。不過由于實(shí)際使用的UCS2,或者UCS4的BMP必然小于0x10000,所以就目前而言,可以認(rèn) 為UTF-16和UCS-2基本相同。但UCS-2只是一個(gè)編碼方案,UTF-16卻要用于實(shí)際的傳輸,所以就不得不考慮字節(jié)序的問題。

UTF-16不兼容ASCII。

5.2.3 UTF-7

UTF-7 (7-位元 Unicode 轉(zhuǎn)換格式(Unicode Transformation Format,簡(jiǎn)寫成 UTF)) 是一種可變長度字元編碼方式,用以將 Unicode 字元以 ASCII 編碼的字元串來呈現(xiàn),可以應(yīng)用在電子郵件傳輸之類的應(yīng)用。

UTF-7并非Unicode標(biāo)準(zhǔn)之一。想要詳細(xì)了解的可以查閱相關(guān)資料。

6、Unicode與UTF

Unicode是內(nèi)存編碼表示方案(是規(guī)范),而UTF是如何保存和傳輸U(kuò)nicode的方案(是實(shí)現(xiàn))。

6.1 UTF的字節(jié)序和BOM

6.1.1 字節(jié)序

UTF-8以字節(jié)為編碼單元,沒有字節(jié)序的問題。UTF-16以兩個(gè)字節(jié)為編碼單元,在解釋一個(gè)UTF-16文本前,首先要弄清楚每個(gè)編碼單元 的字節(jié)序。例如收到一個(gè)“奎”的Unicode編碼是594E,“乙”的Unicode編碼是4E59。如果我們收到UTF-16字節(jié)流“594E”,那 么這是“奎”還是“乙”?

Unicode規(guī)范中推薦的標(biāo)記字節(jié)順序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte Order Mark。BOM是一個(gè)有點(diǎn)小聰明的想法:

在UCS編碼中有一個(gè)叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的編碼是FEFF。而FFFE在UCS中是不存在的字符,所以不應(yīng)該出現(xiàn)在實(shí)際傳輸中。UCS規(guī)范建議我們?cè)趥鬏斪止?jié)流前,先傳輸 字符"ZERO WIDTH NO-BREAK SPACE"。

這樣如果接收者收到FEFF,就表明這個(gè)字節(jié)流是Big-Endian的;如果收到FFFE,就表明這個(gè)字節(jié)流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被稱作BOM。

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

6.1.2 BOM

(1)BOM的來歷?

為了識(shí)別 Unicode 文件,Microsoft 建議所有的 Unicode 文件應(yīng)該以 ZERO WIDTH NOBREAK SPACE(U+FEFF)字符開頭。這作為一個(gè)“特征符”或“字節(jié)順序標(biāo)記(byte-order mark,BOM)”來識(shí)別文件中使用的編碼和字節(jié)順序。

(2)不同的系統(tǒng)對(duì)BOM的支持?

因?yàn)橐恍┫到y(tǒng)或程序不支持BOM,因此帶有BOM的Unicode文件有時(shí)會(huì)帶來一些問題。

①JDK1.5以及之前的Reader都不能處理帶有BOM的UTF-8編碼的文件,解析這種格式的xml文件時(shí),會(huì)拋出異常:Content is not allowed in prolog。“對(duì)于解決方法,之后我會(huì)寫篇文章專門討論該問題。”

②Linux/UNIX 并沒有使用 BOM,因?yàn)樗鼤?huì)破壞現(xiàn)有的 ASCII 文件的語法約定。

③不同的編輯工具對(duì)BOM的處理也各不相同。使用Windows自帶的記事本將文件保存為UTF-8編碼的時(shí)候,記事本會(huì)自動(dòng)在文件開頭插入 BOM(雖然BOM對(duì)UTF-8來說并不是必須的)。而其它很多編輯器用不用BOM是可以選擇的。UTF-8、UTF-16都是如此。

(3)BOM與XML?

XML解析讀取XML文檔時(shí),W3C定義了3條規(guī)則:

①如果文檔中有BOM,就定義了文件編碼;
②如果文檔中沒有BOM,就查看XML聲明中的編碼屬性;
③如果上述兩者都沒有,就假定XML文檔采用UTF-8編碼。

6.2 決定文本的字符集與編碼

軟件通常有三種途徑來決定文本的字符集和編碼。

(1)對(duì)于Unicode文本最標(biāo)準(zhǔn)的途徑是檢測(cè)文本最開頭的幾個(gè)字節(jié)。如:

開頭字節(jié) ? ? ? ?Charset/encoding
?EF BB BF    UTF-8
?FE FF     UTF-16/UCS-2, little endian(UTF-16LE)
?FF FE     UTF-16/UCS-2, big endian(UTF-16BE)
?FF FE 00 00  UTF-32/UCS-4, little endian.
?00 00 FE FF  UTF-32/UCS-4, big-endia

(2)采取一種比較安全的方式來決定字符集及其編碼,那就是彈出一個(gè)對(duì)話框來請(qǐng)示用戶。

然而MBCS文本(ANSI)沒有這些位于開頭的字符集標(biāo)記,現(xiàn)在很多軟件保存文本為Unicode時(shí),可以選擇是否保存這些位于開頭的字符集 標(biāo)記。因此,軟件不應(yīng)該依賴于這種途徑。這時(shí),軟件可以采取一種比較安全的方式來決定字符集及其編碼,那就是彈出一個(gè)對(duì)話框來請(qǐng)示用戶。

(3)采取自己“猜”的方法。

如果軟件不想麻煩用戶,或者它不方便向用戶請(qǐng)示,那它只能采取自己“猜”的方法,軟件可以根據(jù)整個(gè)文本的特征來猜測(cè)它可能屬于哪個(gè) charset,這就很可能不準(zhǔn)了。使用記事本打開那個(gè)“聯(lián)通”文件就屬于這種情況。(把原本屬于ANSI編碼的文件當(dāng)成UTF-8處理,詳細(xì)說明 見:http://blog.csdn.net/omohe/archive/2007/05/29/1630186.aspx)

6.3 記事本的幾種編碼

(1)ANSI編碼?
記事本默認(rèn)保存的編碼格式是:ANSI,即本地操作系統(tǒng)默認(rèn)的內(nèi)碼,簡(jiǎn)體中文一般為GB2312。這個(gè)怎么驗(yàn)證呢?用記事本保存后,使用 EmEditor、EditPlus和UltraEdit之類的文本編輯器打開。推薦使用EmEditor,打開后,在又下角會(huì)顯示編碼:GB2312。

(2)Unicode編碼?
用記事本另存為時(shí),編碼選擇“Unicode”,用EmEditor打開該文件,發(fā)現(xiàn)編碼格式是:UTF-16LE+BOM(有簽名)。用十六進(jìn)制方式查看,發(fā)現(xiàn)開頭兩字節(jié)為:FF FE。這就是BOM。

(3)Unicode big endian?
用記事本另存為時(shí),編碼選擇“Unicode”,用EmEditor打開該文件,發(fā)現(xiàn)編碼格式是:UTF-16BE+BOM(有簽名)。用十六進(jìn)制方式查看,發(fā)現(xiàn)開頭兩字節(jié)為:FE FF。這就是BOM。

(4)UTF-8?
用記事本另存為時(shí),編碼選擇“UTF-8”,用EmEditor打開該文件,發(fā)現(xiàn)編碼格式是:UTF-8(有簽名)。用十六進(jìn)制方式查看,發(fā)現(xiàn)開頭三個(gè)字節(jié)為:EF BB BF。這就是BOM。

7、幾種誤解,以及亂碼產(chǎn)生的原因和解決辦法

7.1 誤解一

在將“字節(jié)串”轉(zhuǎn)化成“UNICODE 字符串”時(shí),比如在讀取文本文件時(shí),或者通過網(wǎng)絡(luò)傳輸文本時(shí),容易將“字節(jié)串”簡(jiǎn)單地作為單字節(jié)字符串,采用每“一個(gè)字節(jié)”就是“一個(gè)字符”的方法進(jìn)行轉(zhuǎn)化。

而實(shí)際上,在非英文的環(huán)境中,應(yīng)該將“字節(jié)串”作為 ANSI 字符串,采用適當(dāng)?shù)木幋a來得到 UNICODE 字符串,有可能“多個(gè)字節(jié)”才能得到“一個(gè)字符”。

通常,一直在英文環(huán)境下做開發(fā)的程序員們,容易有這種誤解。

7.2 誤解二

在 DOS,Windows 98 等非 UNICODE 環(huán)境下,字符串都是以 ANSI 編碼的字節(jié)形式存在的。這種以字節(jié)形式存在的字符串,必須知道是哪種編碼才能被正確地使用。這使我們形成了一個(gè)慣性思維:“字符串的編碼”。

當(dāng) UNICODE 被支持后,Java 中的 String 是以字符的“序號(hào)”來存儲(chǔ)的,不是以“某種編碼的字節(jié)”來存儲(chǔ)的,因此已經(jīng)不存在“字符串的編碼”這個(gè)概念了。只有在“字符串”與“字節(jié)串”轉(zhuǎn)化時(shí),或 者,將一個(gè)“字節(jié)串”當(dāng)成一個(gè) ANSI 字符串時(shí),才有編碼的概念。

不少的人都有這個(gè)誤解。

7.3 分析與解決

第一種誤解,往往是導(dǎo)致亂碼產(chǎn)生的原因。第二種誤解,往往導(dǎo)致本來容易糾正的亂碼問題變得更復(fù)雜。

在這里,我們可以看到,其中所講的“誤解一”,即采用每“一個(gè)字節(jié)”就是“一個(gè)字符”的轉(zhuǎn)化方法,實(shí)際上也就等同于采用 iso-8859-1 進(jìn)行轉(zhuǎn)化。因此,我們常常使用 bytes = string.getBytes("iso-8859-1") 來進(jìn)行逆向操作,得到原始的“字節(jié)串”。然后再使用正確的 ANSI 編碼,比如 string = new String(bytes, "GB2312"),來得到正確的“UNICODE 字符串”。

8、參考與深入閱讀學(xué)習(xí)資料

posted on 2011-08-19 00:25 Vcer-JZ 閱讀(667) 評(píng)論(0)  編輯 收藏 引用 所屬分類: MFC

導(dǎo)航

統(tǒng)計(jì)

隨筆分類

隨筆檔案

搜索

最新評(píng)論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲国产一区二区精品专区| 狠狠久久五月精品中文字幕| 一本一本a久久| 日韩西西人体444www| 欧美天天视频| 午夜在线电影亚洲一区| 亚洲欧美视频一区二区三区| 国产丝袜一区二区三区| 久久久欧美精品sm网站| 美女久久网站| 亚洲深夜福利| 香蕉久久国产| 亚洲国产精品第一区二区| 欧美激情亚洲激情| 欧美日韩一区二区三区| 欧美怡红院视频一区二区三区| 久久都是精品| 亚洲精品女av网站| 亚洲一区二区三区四区中文| 狠狠综合久久| 亚洲人成人77777线观看| 国产精品久久久久久久第一福利| 久久久久久久国产| 欧美国产高清| 久久aⅴ乱码一区二区三区| 久久久久久高潮国产精品视| 日韩小视频在线观看专区| 亚洲综合99| 9i看片成人免费高清| 亚洲欧美卡通另类91av| 亚洲国产成人久久综合| 亚洲伊人网站| 日韩视频在线观看免费| 欧美有码视频| 亚洲欧美999| 欧美国产日韩视频| 久久久久久久激情视频| 欧美精品网站| 美日韩精品免费| 国产精品美女主播| 91久久在线观看| 极品日韩久久| 香蕉久久夜色精品国产| 在线一区日本视频| 麻豆成人小视频| 久久久久国内| 国产伦理精品不卡| 99re66热这里只有精品3直播| 在线成人激情黄色| 欧美在线播放一区| 亚洲综合视频一区| 欧美日韩视频在线第一区| 欧美成人精品不卡视频在线观看 | 中文亚洲欧美| 亚洲免费高清视频| 美女久久网站| 欧美黄污视频| 亚洲国产精品久久久久秋霞影院| 欧美一级二级三级蜜桃| 欧美一级视频| 国产精品久久久久久久久| 日韩一区二区精品葵司在线| 亚洲精品影视在线观看| 免费日韩一区二区| 欧美激情视频在线播放| 亚洲国产精品高清久久久| 久久久水蜜桃| 欧美成人精品一区二区| 在线免费精品视频| 久久中文字幕一区| 亚洲高清激情| 亚洲桃色在线一区| 国产精品户外野外| 亚洲欧美自拍偷拍| 久久裸体艺术| 亚洲激情欧美| 欧美日韩在线播放三区| 中文高清一区| 久久精品青青大伊人av| 国产日韩欧美一区二区三区在线观看| 亚洲一区二区三区在线| 久久精品夜色噜噜亚洲a∨ | 欧美日本精品| 一区二区三区免费观看| 亚洲欧美一级二级三级| 国产欧美一区二区精品性| 欧美在线3区| 亚洲国产岛国毛片在线| 一本色道久久综合一区| 国产精品每日更新| 久久精品综合网| 亚洲精品国久久99热| 亚洲一区自拍| 狠狠色丁香婷婷综合| 欧美成人嫩草网站| 亚洲在线观看视频网站| 久久先锋资源| 亚洲视频一二三| 黄色精品一二区| 欧美日韩一区二区欧美激情 | 亚洲人成在线播放| 欧美一区二区三区久久精品茉莉花 | 亚洲国产成人午夜在线一区| 亚洲一区不卡| 亚洲第一精品久久忘忧草社区| 欧美日韩成人一区二区三区| 午夜精品影院| 亚洲三级性片| 老司机凹凸av亚洲导航| 中文精品99久久国产香蕉| 韩国在线视频一区| 国产精品激情av在线播放| 久久天天躁狠狠躁夜夜爽蜜月| 亚洲乱亚洲高清| 免费毛片一区二区三区久久久| 亚洲综合欧美日韩| 亚洲破处大片| 一区二区三区中文在线观看 | 欧美一级片在线播放| 亚洲国产日韩欧美在线图片| 久久国产精品一区二区| 一区二区三区国产精华| 一区二区在线看| 国产欧美一区二区三区在线老狼| 欧美剧在线观看| 男人的天堂亚洲在线| 久久国产精品网站| 亚洲一区二区在线视频| 亚洲开发第一视频在线播放| 另类av导航| 久久人91精品久久久久久不卡| 午夜精品视频一区| 一本色道久久88亚洲综合88| **网站欧美大片在线观看| 国产伊人精品| 国产亚洲一级高清| 国产视频精品va久久久久久| 国产精品日韩精品欧美精品| 欧美日韩成人在线观看| 欧美黄色片免费观看| 有码中文亚洲精品| 国产精品日韩精品欧美精品| 欧美吻胸吃奶大尺度电影| 欧美日本免费| 欧美午夜国产| 国产精品拍天天在线| 国产精品国产三级国产普通话蜜臀 | 99热这里只有精品8| 亚洲精品美女久久久久| 亚洲国产日韩欧美在线99| 91久久精品国产91久久性色| 最新国产の精品合集bt伙计| 亚洲国产精品一区二区久| 91久久黄色| 亚洲精品一区中文| 亚洲视频你懂的| 亚洲欧美日韩精品在线| 欧美影院成年免费版| 久久国产天堂福利天堂| 老司机精品导航| 欧美日本成人| 国产精品夜夜夜| 韩日欧美一区二区| 亚洲国产精品电影| 亚洲作爱视频| 欧美制服丝袜第一页| 老司机凹凸av亚洲导航| 亚洲激情视频网站| 亚洲亚洲精品在线观看 | 亚洲精品一区二区三区在线观看| 日韩一二三区视频| 亚洲一区二区在线免费观看| 久久黄金**| 欧美激情精品久久久六区热门 | 亚洲精品中文字幕女同| 午夜激情久久久| 欧美成年人视频| 一区二区三区欧美在线观看| 久久精品123| 欧美视频一区二区| 尤物在线观看一区| 亚洲一区二区成人| 免费在线视频一区| 亚洲一区不卡| 欧美成人午夜| 国产偷久久久精品专区| 亚洲伦伦在线| 久久久夜色精品亚洲| 亚洲精品在线免费| 久久成人免费网| 国产精品a级| 亚洲日本激情| 久久久久久高潮国产精品视| 亚洲人成网站色ww在线| 久久国内精品视频| 国产精品久久久久久久久久三级 | 亚洲免费观看视频| 久久香蕉国产线看观看网| 一区二区三区色| 欧美精品性视频|