轉自:dbzhang800的 http://hi.baidu.com/cyclone/blog/item/d299af51e04aed868d543064.html
小結得好好呀!
字符集與編碼問題小結
寫在前面一直想整理一點文字編碼相關的東西,卻由於能力不夠,始終不知道如何下手。看到論壇中編碼一再被提起,終於決定嘗試着整理一下。 --2010.05.30 編碼的引入我們都瞭解,計算機只能存儲2進制,也是就010100...,而無法存儲“abc...”。當有人想把文字存儲到計算機時,編碼的故事就開始了... 既然計算機只能,只能存放二進制,那麼我們就把“abc...”通過某種方式變成二進制不就解決了麼? 比如,
哎,等等,爲什麼要用 0x41 表示 a 呢,如果有人用下面的方式怎麼辦?
ASCII有人用 0x41 代表a,有人用 0x81 表示。語言不通,不同的計算機無法交流。美國人很早發現了這種問題,爲便於交流指定了編碼標準,於是有了: ASCII (American Standard Code for Information)
ISO-8859-*ASCII 解決了美國人的問題,但很快,其他國家發現了這個編碼不能滿足自己國家的需要。法國、德國等國家暫且不說,英國都發現ASCII有問題:英鎊符號“£”去哪兒了?現在好了, 既想與ASCII兼容,有要添加ASCII沒有的文字符號,怎麼辦?擴展一下吧! 由於ASCII碼只使用了7個二進制位,也就是說一個字節可以表示的256個數字中,它僅使用了0~127這128個碼位,剩下的128個碼位便可以用來做擴展,用來表示一些特定語言所獨有的字符 因此對這多餘的128個碼位的不同擴展,就形成了一系列ISO-8859-*的標準。例如爲英語作了專門擴展的字符集編碼標準編號爲ISO-8859-1,也叫做Latin-1。 ISO-8859-* (*代表1~11,13~16)共15個編碼方案,解決了 拉丁字母的語言(主要是歐洲國家的語言),使用西裏爾字母的東歐語言、希臘語、泰語、現代阿拉伯語、希伯來語等。 * 這些編碼方案在當時解決了這些國家的問題,但不同的編碼如同軍閥割據,同一勢力範圍內交流沒問題,但不能普遍通用。比如 \xA3 在使用 Latin-1 的國家看來,是英鎊符號“£”,而在使用 Latin-2的國家看來,卻是另一個符號 “Ł”。而且無法在一個文件內同時出現這兩個符號。這個問題的解決,需要unicode。 ISO-2022 與 EUCISO-8859-* 解決了多數語言的編碼問題,可是,漢語、日語及韓語字數衆多,無法用單一個8位字符來表達,也就是無法通過類似 ISO-8859-*的方式解決。於是有了 ISO-2022 ISO-2022提供了這樣一種技術,它能在一種字符編碼中支持多種字符集,可以用8位或16位來表示一個文字(字符),是一種變長的編碼,這樣,就能表示中日韓的字符了。該編碼還有個顯著的特點,就是所有的字節都是以0開始。 ISO-2022 在日本用的比較普遍,在中國反倒是很少使用。儘管如此,還是用中文的 ISO-2022-CN 簡單說一下: 在繼續之前,我們先提一下GB2312:GB2312 中規定了漢字的區位碼,同時指定 ISO-2022 (等同GB 2311) 爲包裝方式。 漢字“文”字在46區36位,用 ISO 2022 包裝時,字節序列是:
前面說了,ISO-2022 在國內很少使用,那麼國內用的什麼編碼方案呢? 這就是 EUC-CN: EUC (Extended Unix Code),是一個主要用於日文、韓文、簡體中文 的多字節編碼系統,它基於ISO-2020標準。它使用了一些兼容於ISO-2022區位碼的94x94編碼表,把每個區位加上0xA0來表示,以便兼容於ASCII。 今天通常說的 GB2312 編碼都是指 EUC 包裝的 GB2312 編碼。 EUC-GB2312 與區位碼的關係:
UnicodeUnicode是由於傳統的字符編碼方式的侷限性而產生的,例如:
於是一個將所有國家所有語種的所有文字進行統一編碼的方案開始了... Unicode與UCS1980年代,有兩個組織分別開始開發適用於各國語言的通用碼,但不久他們便發現了對方的存在。
ISO與Unicode是兩個不同的組織,因此最初制定了不同的標準;但自從unicode2.0開始,unicode採用了與ISO 10646-1相同的字庫和字碼,ISO也承諾ISO10646將不會給超出0×10FFFF的UCS-4編碼賦值,使得兩者保持一致。最終,兩者統一了抽象字符集(即任何一個在Unicode中存在的字符,在UCS中也存在),且最靠前的65535個字符也統一了字符的編碼。 編碼字符集與字符編碼在傳統意義上,沒有字符集和編碼的區分,比如GB2312、Latin1等都是既指代字符集又指代編碼方案。
按照慣例,人們認爲字符集和字符編碼是同義詞,但現代的編碼方案 Unicode,沒有遵循這種慣例。 Unicode 是一個字符集合,它給集合中的每個字符都指定一了個代號。 當我們要把這個代號存到計算機中時,需要把它變成一個字節的序列。不同的變換方式引入了 UTF
UTF
UTF 還涉及到字節序的問題。字節順序標記(Byte Order Mark, 簡稱BOM)出現在Unicode流開端,說明編碼類型。BOM是一個有點小聰明的想法。下面是常用的BOM:
GB18030
其他GBKGBK (Microsoft Code Page 936) 相傳是微軟公司在 EUC-GB2312 的基礎上擴充了 Unicode 1.1 (GB13000.1-93) 而來, 最早出現於 Windows 95。沒有對應的國家標準,只有一個《全國信息技術標準化技術 委員會 漢字內碼擴展規範(GBK) 1.0》。
base64Base64是網絡上最常見的用於傳輸8Bit字節代碼的編碼方式之一 Base64要求把每三個8Bit的字節轉換爲四個6Bit的字節(3*8 = 4*6 = 24),然後把6Bit再添兩位高位0,組成四個8Bit的字節,也就是說,轉換後的字符串理論上將要比原來的長1/3。 HZ將 EUC-GB2312 的各字節最高位去掉,再在前後分別加上轉義字符,例如“文”: ~{ <0x4E> <0x44> ~} |