關於編碼ansi、GB2312、unicode與utf-8的區別

原文:http://zz563143188.iteye.com/blog/1842131
關於編碼ansi、GB2312、unicode與utf-8的區別
1.中文操作系統默認ansi編碼,生成的txt文件默認爲ansi編碼.
2.unicode是國際通用編碼.
3.utf-8編碼是unicode編碼在網絡之間(主要是網頁)傳輸時的一種“變通”和“橋樑”編碼。utf-8在網絡之間傳輸時可以節約數據量。

按照utf-8創始人的願望:
端(unicode)——傳輸(utf-8)——端(unicode)

但是,後來,許多網站開發者在開發網頁時直接使用utf-8編碼。
端(utf-8)——傳輸(utf-8)——端(utf-8)


所以,在瀏覽器上看到的編碼是:unicode(utf-8)。正因爲在瀏覽器上這麼並列地列出unicode(utf-8),造成許多網友(甚至不少程序員)誤認爲unicode=utf-8。其實,按照utf-8創始人的原意,在開發網頁時使用utf-8編碼是錯誤的做法,並且,早期的瀏覽器也不支持解析utf-8編碼。但是,衆人的力量是巨大的,微軟不得不“趨炎附勢”,在瀏覽器上支持解析utf-8編碼。

問題是:utf-8編碼影響了網站開發者,或者說,網站開發者“擴展”了utf-8編碼的使用範圍。但是,網站開發者仍然無法影響各類文檔的開發者,所以,word文檔和一些國際通用的文檔仍然使用unicode編碼而不使用utf-8編碼。

比如:“嚴”的Unicode碼是4E25,UTF-8編碼是E4B8A5,兩者是不一樣的。

在中文和日文操作系統裏生成的(txt和xml)文件的編碼雖然都是ansi,但是,在簡體中文系統下,ansi 編碼代表 GB2312 編碼,在日文操作系統下,ansi 編碼代表 JIS 編碼。不同 ansi 編碼之間互不兼容,當信息在國際間交流時,無法將屬於兩種語言的文字,存儲在同一段 ansi 編碼的文本中。

結論:國際文檔(txt和xml)使用unicode編碼是正宗做法;操作系統和瀏覽器都能夠“理解”unicode編碼。瀏覽器“迫於壓力”才“理解”utf-8編碼。但是,操作系統有時只認unicode編碼。
Unicode與Unicode big endian的區別:你吃雞蛋時先吃小頭還是先吃大頭?Unicode與Unicode big endian的區別就是在編碼時小頭優先與大頭優先的區別。“隨波逐流”使用Unicode就OK了。
我(不是程序員)這幾年一直因爲編碼問題,感到非常困惑,查了許多資料,在國際文檔的實際應用中也遇到過許多問題,所以,“感性”地總結了上述觀點,不一定準確(或者說,不一定正確)。

Unicode、UTF-8 和 ISO8859-1到底有什麼區別
1.本文主要包括以下幾個方面:編碼基本知識,Java,系統軟件,url,工具軟件等。

在下面的描述中,將以"中文"兩個字爲例,經查表可以知道其GB2312編碼是"d6d0 cec4",Unicode編碼爲"4e2d 6587",UTF編碼就是"e4b8ad e69687"。注意,這兩個字沒有iso8859-1編碼,但可以用iso8859-1編碼來"表示"。
2. 編碼基本知識

最早的編碼是iso8859-1,和ascii編碼相似。但爲了方便表示各種各樣的語言,逐漸出現了很多標準編碼,重要的有如下幾個。

2.1. iso8859-1 通常叫做Latin-1

屬於單字節編碼,最多能表示的字符範圍是0-255,應用於英文系列。比如,字母a的編碼爲0x61=97。

很明顯,iso8859-1編碼表示的字符範圍很窄,無法表示中文字符。但是,由於是單字節編碼,和計算機最基礎的表示單位一致,所以很多時候,仍舊使用iso8859-1編碼來表示。而且在很多協議上,默認使用該編碼。比如,雖然"中文"兩個字不存在iso8859-1編碼,以gb2312編碼爲例,應該是"d6d0 cec4"兩個字符,使用iso8859-1編碼的時候則將它拆開爲4個字節來表示:"d6 d0 ce c4"(事實上,在進行存儲的時候,也是以字節爲單位處理的)。而如果是UTF編碼,則是6個字節"e4 b8 ad e6 96 87"。很明顯,這種表示方法還需要以另一種編碼爲基礎。
2.2. GB2312/GBK

這就是漢子的國標碼,專門用來表示漢字,是雙字節編碼,而英文字母和iso8859-1一致(兼容iso8859-1編碼)。其中gbk編碼能夠用來同時表示繁體字和簡體字,而gb2312只能表示簡體字,gbk是兼容gb2312編碼的。
2.3. unicode

這是最統一的編碼,可以用來表示所有語言的字符,而且是定長雙字節(也有四字節的)編碼,包括英文字母在內。所以可以說它是不兼容iso8859-1編碼的,也不兼容任何編碼。不過,相對於iso8859-1編碼來說,uniocode編碼只是在前面增加了一個0字節,比如字母a爲"00 61"。

需要說明的是,定長編碼便於計算機處理(注意GB2312/GBK不是定長編碼),而unicode又可以用來表示所有字符,所以在很多軟件內部是使用unicode編碼來處理的,比如java。
2.4. UTF

考慮到unicode編碼不兼容iso8859-1編碼,而且容易佔用更多的空間:因爲對於英文字母,unicode也需要兩個字節來表示。所以unicode不便於傳輸和存儲。因此而產生了utf編碼,utf編碼兼容iso8859-1編碼,同時也可以用來表示所有語言的字符,不過,utf編碼是不定長編碼,每一個字符的長度從1-6個字節不等。另外,utf編碼自帶簡單的校驗功能。一般來講,英文字母都是用一個字節表示,而漢字使用三個字節。

注意,雖然說utf是爲了使用更少的空間而使用的,但那只是相對於unicode編碼來說,如果已經知道是漢字,則使用GB2312/GBK無疑是最節省的。不過另一方面,值得說明的是,雖然utf編碼對漢字使用3個字節,但即使對於漢字網頁,utf編碼也會比unicode編碼節省,因爲網頁中包含了很多的英文字符。
3. java對字符的處理

在java應用軟件中,會有多處涉及到字符集編碼,有些地方需要進行正確的設置,有些地方需要進行一定程度的處理。

3.1. getBytes(charset)

這是java字符串處理的一個標準函數,其作用是將字符串所表示的字符按照charset編碼,並以字節方式表示。注意字符串在java內存中總是按unicode編碼存儲的。比如"中文",正常情況下(即沒有錯誤的時候)存儲爲"4e2d 6587",如果charset爲"gbk",則被編碼爲"d6d0 cec4",然後返回字節"d6 d0 ce c4"。如果charset爲"utf8"則最後是"e4 b8 ad e6 96 87"。如果是"iso8859-1",則由於無法編碼,最後返回 "3f 3f"(兩個問號)。
3.2. new String(charset)

這是java字符串處理的另一個標準函數,和上一個函數的作用相反,將字節數組按照charset編碼進行組合識別,最後轉換爲unicode存儲。參考上述getBytes的例子,"gbk" 和"utf8"都可以得出正確的結果"4e2d 6587",但iso8859-1最後變成了"003f 003f"(兩個問號)。

因爲utf8可以用來表示/編碼所有字符,所以new String( str.getBytes( "utf8" ), "utf8" ) === str,即完全可逆。
3.3. setCharacterEncoding()

該函數用來設置http請求或者相應的編碼。

對於request,是指提交內容的編碼,指定後可以通過getParameter()則直接獲得正確的字符串,如果不指定,則默認使用iso8859-1編碼,需要進一步處理。參見下述"表單輸入"。值得注意的是在執行setCharacterEncoding()之前,不能執行任何getParameter()。java doc上說明:This method must be called prior to reading request parameters or reading input using getReader()。而且,該指定只對POST方法有效,對GET方法無效。分析原因,應該是在執行第一個getParameter()的時候,java將會按照編碼分析所有的提交內容,而後續的getParameter()不再進行分析,所以setCharacterEncoding()無效。而對於GET方法提交表單是,提交的內容在URL中,一開始就已經按照編碼分析所有的提交內容,setCharacterEncoding()自然就無效。
4.iso-8859-1是JAVA網絡傳輸使用的標準 字符集,而gb2312是標準中文字符集,當你作出提交表單等需要網絡傳輸的操作的時候,就需要把 iso-8859-1轉換爲gb2312字符集顯示,否則如果按瀏覽器的gb2312格式來解釋iso-8859-1字符集的話,由於2者不兼容,所以會 是亂碼.
轉自http://hi.baidu.com/libo20475/blog/item/2761afdea8d3105d94ee37f2.html
unicode和utf-8是什麼關係
Unicode的最初目標,是用1個16位的編碼來爲超過65000個字符提供映射。但這還不夠,它不能覆蓋全部歷史上的文字,也不能解決傳輸的問題(implantation head-ache's),尤其在那些基於網絡的應用中。已有的軟件必須做大量的工作來實現16位的數據。
  因此,Unicode用一些基本的保留字符制定了三套編碼方式。它們分別是UTF-8,UTF-16和UTF-32。正如名字所示,在UTF-8中,字符是以8位序列來編碼的,用一個或幾個字節來表示一個字符。這種方式的最大好處,是UTF-8保留了ASCII字符的編碼做爲它的一部分,例如,在UTF-8和ASCII中,“A”的編碼都是0x41. UTF-16和UTF-32分別是Unicode的16位和32位編碼方式。考慮到最初的目的,通常說的Unicode就是指UTF-16。在討論Unicode時,搞清楚哪種編碼方式非常重要。Unicode:
unicode.org制定的編碼機制, 要將全世界常用文字都函括進去.
在1.0中是16位編碼, 由U+0000到U+FFFF. 每個2byte碼對應一個字符; 在2.0開始拋棄了16位限制, 原來的16位作爲基本位平面, 另外增加了16個位平面, 相當於20位編碼, 編碼範圍0到0x10FFFF.
UTF: Unicode/UCS Transformation Format
UTF-8, 8bit編碼, ASCII不作變換, 其他字符做變長編碼, 每個字符1-3 byte. 通常作爲外碼. 有以下優點:
* 與CPU字節順序無關, 可以在不同平臺之間交流
* 容錯能力高, 任何一個字節損壞後, 最多隻會導致一個編碼碼位損失, 不會鏈鎖錯誤(如GB碼錯一個字節就會整行亂碼)
UTF-16, 16bit編碼, 是變長碼, 大致相當於20位編碼, 值在0到0x10FFFF之間, 基本上就是unicode編碼的實現. 它是變長碼, 與CPU字序有關, 但因爲最省空間, 常作爲網絡傳輸的外碼.
UTF-16是unicode的preferred encoding.
UTF-32, 僅使用了unicode範圍(0到0x10FFFF)的32位編碼, 相當於UCS-4的子集.
UTF與unicode的關係:
Unicode是一個字符集, 可以看作爲內碼.
而UTF是一種編碼方式, 它的出現是因爲unicode不適宜在某些場合直接傳輸和處理. UTF-16直接就是unicode編碼, 沒有變換, 但它包含了0x00在編碼內, 頭256字節碼的第一個byte都是0x00, 在操作系統(C語言)中有特殊意義, 會引起問題. 採用UTF-8編碼對unicode的直接編碼作些變換可以避免這問題, 並帶來一些優點
utf-8與utf-16的區別
UTF8 和 UTF16 都是變長表示的,爲啥歐美技術宅會覺得太浪費了咧?因爲歐美字符 0x0000 - 0x00FF 就搞定了,UTF8 最小變長是 1 個字節,而 UTF16 變長是 2 個字節,
.utf-8 與 uft-16 表示 'a' a的ascii是0X61
utf-8爲[0X61]
uft-16 [0x00,0X61]
發佈了37 篇原創文章 · 獲贊 33 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章