轉: JAVA字元編碼系列一:Unicode,GBK,GB2312,UTF-8概念基礎

來源:互聯網
上載者:User
這兩天抽時間又總結/整理了一下各種編碼的實際編碼方式,和在Java應用中的使用方式,在這裡記錄下來以便日後參考。為了構成一個完整的對文字編碼的認識和深入把握,以便處理在Java開發過程中遇到的各種問題,特別是亂碼問題,我覺得組成一個系列來描述和分析更好一些,包括三篇文章:第一篇:JAVA字元編碼系列一:Unicode,GBK,GB2312,UTF-8概念基礎第二篇:JAVA字元編碼系列二:Unicode,ISO-8859,GBK,UTF-8編碼及相互轉換第三篇:JAVA字元編碼系列三:Java應用中的編碼問題 第一篇:JAVA字元編碼系列一:Unicode,GBK,GB2312,UTF-8概念基礎本部分採用重用,轉載一篇文章來完成這部分的目標。來源:holen'blog   對字元編碼與Unicode,ISO 10646,UCS,UTF8,UTF16,GBK,GB2312的理解地址:http://blog.donews.com/holen/archive/2004/11/30/188182.aspx  Unicode:

unicode.org制定的編碼機制, 要將全世界常用文字都函括進去.
在1.0中是16位編碼, 由U+0000到U+FFFF. 每個2byte碼對應一個字元; 在2.0開始拋棄了16位限制, 原來的16位作為基本位平面, 另外增加了16個位平面, 相當於20位編碼, 編碼範圍0到0x10FFFF.

UCS:

ISO制定的ISO10646標準所定義的 Universal Character Set, 採用4byte編碼.

Unicode與UCS的關係:

ISO
與unicode.org是兩個不同的組織, 因此最初制定了不同的標準; 但自從unicode2.0開始, unicode採用了與ISO
10646-1相同的字型檔和字碼, ISO也承諾ISO10646將不會給超出0x10FFFF的UCS-4編碼賦值, 使得兩者保持一致.

UCS的編碼方式:

  • UCS-2, 與unicode的2byte編碼基本一樣.
  • UCS-4, 4byte編碼, 目前是在UCS-2前加上2個全零的byte.

    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的直接編碼作些變換可以避免這問題, 並帶來一些優點.

    中國國標編碼:

  • GB 13000: 完全等同於ISO 10646-1/Unicode 2.1, 今後也將隨ISO 10646/Unicode的標準更改而同步更改.
  • GBK: 對GB2312的擴充, 以容納GB2312字元集範圍以外的Unicode 2.1的統一漢字部分, 並且增加了部分unicode中沒有的字元.
  • GB 18030-2000: 基於GB 13000, 作為Unicode 3.0的GBK擴充版本, 覆蓋了所有unicode編碼,
    地位等同於UTF-8, UTF-16, 是一種unicode編碼形式. 變長編碼, 用單位元組/雙位元組/4位元組對字元編碼.
    GB18030向下相容GB2312/GBK.
    GB 18030是中國所有非手持/嵌入式電腦系統的強制實施標準.

    -------------------------------

     

    什麼是 UCS 和 ISO 10646?

    國際標準 ISO 10646
    定義了 通用字元集 (Universal Character Set, UCS)
    . UCS 是所有其他字元集標準的一個超集. 它保證與其他字元集是雙向相容的. 就是說, 如果你將任何文本字串翻譯到 UCS格式, 然後再翻譯回原編碼, 你不會丟失任何資訊.

    UCS 包含了用於表達所有已知語言的字元. 不僅包括拉丁語,希臘語, 斯拉夫語,希伯來語,阿拉伯語,亞美尼亞語和喬治亞語的描述,
    還包括中文, 日文和韓文這樣的表意字元, 以及 平假名, 片假名, 孟加拉語, 旁遮普語果魯穆奇字元(Gurmukhi), 泰米爾語,
    印.埃納德語(Kannada), Malayalam, 泰國語, 寮國語, 漢語拼音(Bopomofo), Hangul,
    Devangari, Gujarati, Oriya, Telugu 以及其他數也數不清的語. 對於還沒有加入的語言,
    由於正在研究怎樣在電腦中最好地編碼它們, 因而最終它們都將被加入. 這些語言套件括 Tibetian, 高棉語, Runic(古代北歐文字),
    埃塞俄比亞語, 其他表意字元, 以及各種各樣的印-歐語系的語言, 還包括挑選出來的藝術語言比如 Tengwar, Cirth 和
    克林貢語(Klingon). UCS 還包括大量的圖形的, 印刷用的, 數學用的和科學用的符號, 包括所有由 TeX, Postscript,
    MS-DOS,MS-Windows, Macintosh, OCR 字型, 以及許多其他文書處理和出版系統提供的字元.

    ISO 10646 定義了一個 31 位的字元集. 然而, 在這巨大的編碼空間中, 迄今為止只分配了前 65534 個碼位 (0x0000 到 0xFFFD). 這個 UCS 的 16位子集稱為 基本多語言面 (Basic Multilingual Plane, BMP)
    .
    將被編碼在 16 位 BMP 以外的字元都屬於非常特殊的字元(比如表意字元), 且只有專家在曆史和科學領域裡才會用到它們. 按當前的計劃,
    將來也許再也不會有字元被分配到從 0x000000 到 0x10FFFF 這個覆蓋了超過 100 萬個潛在的未來字元的 21
    位的編碼空間以外去了. ISO 10646-1 標準第一次發表於 1993 年, 定義了字元集與 BMP 中內容的架構. 定義 BMP
    以外的字元編碼的第二部分 ISO 10646-2 正在準備中, 但也許要過好幾年才能完成. 新的字元仍源源不斷地加入到 BMP 中,
    但已經存在的字元是穩定的且不會再改變了.

    UCS 不僅給每個字元分配一個代碼, 而且賦予了一個正式的名字. 表示一個 UCS 或 Unicode 值的十六進位數, 通常在前面加上
    "U+", 就象 U+0041 代表字元"拉丁大寫字母A". UCS 字元 U+0000 到 U+007F 與 US-ASCII(ISO
    646) 是一致的, U+0000 到 U+00FF 與 ISO 8859-1(Latin-1) 也是一致的. 從 U+E000 到
    U+F8FF, 已經 BMP 以外的大範圍的編碼是為私用保留的.

    什麼是組合字元?

    UCS裡有些編碼點分配給了 組合字元
    .它們類似於打字機上的無間隔重音鍵.
    單個的組合字元不是一個完整的字元. 它是一個類似於重音符或其他指示標記, 加在前一個字元後面. 因而, 重音符可以加在任何字元後面.
    那些最重要的被加重的字元, 就象普通語言的正字法(orthographies of common languages)裡用到的那種, 在
    UCS 裡都有自己的位置, 以確保同老的字元集的向後相容性. 既有自己的編碼位置, 又可以表示為一個一般字元跟隨一個組合字元的被加重字元,
    被稱為 預作字元(precomposed characters)
    . UCS
    裡的預作字元是為了同沒有預作字元的舊編碼, 比如 ISO 8859, 保持向後相容性而設的.
    組合字元機制允許在任何字元後加上重音符或其他指示標記, 這在科學符號中特別有用, 比如數學方程式和國際音標字母,
    可能會需要在一個基底字元後組合上一個或多個指示標記.

    組合字元跟隨著被修飾的字元. 比如, 德語中的母音變音字元 ("拉丁大寫字母A 加上分音符號"), 既可以表示為 UCS 碼 U+00C4
    的預作字元, 也可以表示成一個普通 "拉丁大寫字母A" 跟著一個"組合分音符號":U+0041 U+0308 這樣的組合.
    當需要堆疊多個重音符, 或在一個基底字元的上面和下面都要加上組合標記時, 可以使用多個組合字元. 比如在泰國文中,
    一個基底字元最多可加上兩個組合字元.

    什麼是 UCS 實現層級?

    不是所有的系統都需要支援象組合字元這樣的 UCS 裡所有的先進機制. 因此 ISO 10646 指定了下列三種實現層級:

    層級1
    不支援組合字元和 Hangul Jamo 字元 (一種特別的, 更加複雜的韓國文的編碼, 使用兩個或三個子字元來編碼一個韓文音節)
    層級2

    似於層級1, 但在某些文字中, 允許一列固定的組合字元 (例如, 希伯來文, 阿拉伯文, Devangari, 孟加拉語, 果魯穆奇語,
    Gujarati, Oriya, 泰米爾語, Telugo, 印.埃納德語, Malayalam, 泰國語和寮國語).
    如果沒有這最起碼的幾個組合字元, UCS 就不能完整地表達這些語言.
    層級3
    支援所有的 UCS 字元, 例如數學家可以在任意一個字元上加上一個 tilde(顎化符號,西班牙語字母上面的~)或一個箭頭(或兩者都加).
    什麼是 Unicode?

    曆史上, 有兩個獨立的, 創立單一字元集的嘗試. 一個是國際標準組織(ISO)
    的 ISO 10646 項目, 另一個是由(一開始大多是美國的)多語言軟體製造商組成的協會組織的 Unicode 項目
    .
    幸運的是, 1991年前後, 兩個項目的參與者都認識到, 世界不需要兩個不同的單一字元集. 它們合并雙方的工作成果,
    並為創立一個單一編碼錶而協同工作. 兩個項目仍都存在並獨立地公布各自的標準, 但 Unicode 協會和 ISO/IEC JTC1/SC2
    都同意保持 Unicode 和 ISO 10646 標準的碼錶相容, 並緊密地共同調整任何未來的擴充.

    那麼 Unicode 和 ISO 10646 不同在什麼地方?

    Unicode 協會公布的 Unicode 標準
    嚴密地包含了 ISO 10646-1 實現層級3的基本多語言面. 在兩個標準裡所有的字元都在相同的位置並且有相同的名字.

    Unicode 標準額外定義了許多與字元有關的語義符號學, 一般而言是對於實現高品質的印刷出版系統的更好的參考. Unicode
    詳細說明了繪製某些語言(比如阿拉伯語)表達形式的演算法, 處理雙向文字(比如拉丁與希伯來文混合文字)的演算法和 排序與字串比較 所需的演算法,
    以及其他許多東西.

    另一方面, ISO 10646 標準, 就象廣為人知的 ISO 8859 標準一樣, 只不過是一個簡單的字元集表.
    它指定了一些與標準有關的術語, 定義了一些編碼的別名, 並包括了規範說明, 指定了怎樣使用 UCS 串連其他 ISO 標準的實現, 比如
    ISO 6429 和 ISO 2022. 還有一些與 ISO 緊密相關的, 比如 ISO 14651 是關於 UCS 字串排序的.

    考慮到 Unicode 標準有一個易記的名字, 且在任何好的書店裡的 Addison-Wesley 裡有, 只花費 ISO
    版本的一小部分, 且包括更多的輔助資訊, 因而它成為使用廣泛得多的參考也就不足為奇了. 然而, 一般認為, 用於列印 ISO 10646-1
    標準的字型在某些方面的品質要高於用於列印 Unicode 2.0的. 專業字型設計者總是被建議說要兩個標準都實現,
    但一些提供的範例字形有顯著的區別. ISO 10646-1 標準同樣使用四種不同的風格變體來顯示表意文字如中文, 日文和韓文 (CJK), 而
    Unicode 2.0 的表裡只有中文的變體. 這導致了普遍的認為 Unicode 對日本使用者來說是不可接收的傳說, 儘管是錯誤的.

    什麼是 UTF-8?

    首先 UCS 和 Unicode 只是分配整數給字元的編碼錶. 現在存在好幾種將一串字元表示為一串位元組的方法. 最顯而易見的兩種方法是將
    Unicode 文本儲存為 2 個 或 4 個位元組序列的串. 這兩種方法的正式名稱分別為 UCS-2 和 UCS-4. 除非另外指定,
    否則大多數的位元組都是這樣的(Bigendian convention). 將一個 ASCII 或 Latin-1 的檔案轉換成 UCS-2
    只需簡單地在每個 ASCII 位元組前插入 0x00. 如果要轉換成 UCS-4, 則必須在每個 ASCII 位元組前插入三個 0x00.

    在 Unix 下使用 UCS-2 (或 UCS-4) 會導致非常嚴重的問題. 用這些編碼的字串會包含一些特殊的字元, 比如 '/0'
    或 '/', 它們在 檔案名稱和其他 C 庫函數參數裡都有特別的含義. 另外, 大多數使用 ASCII 檔案的 UNIX 下的工具,
    如果不進行重大修改是無法讀取 16 位的字元的. 基於這些原因, 在檔案名稱, 文字檔, 環境變數等地方, UCS-2
    不適合作為 Unicode
    的外部編碼.

    在 ISO 10646-1 Annex R
    和 RFC 2279
    裡定義的 UTF-8
    編碼沒有這些問題. 它是在 Unix 風格的作業系統下使用 Unicode 的明顯的方法.

    UTF-8 有一下特性:

    • UCS 字元 U+0000 到 U+007F (ASCII) 被編碼為位元組 0x00 到 0x7F (ASCII 相容). 這意味著只包含 7 位 ASCII 字元的檔案在 ASCII 和 UTF-8 兩種編碼方式下是一樣的.
    • 所有 >U+007F 的 UCS 字元被編碼為一個多個位元組的串, 每個位元組都有標記位集. 因此, ASCII 位元組 (0x00-0x7F) 不可能作為任何其他字元的一部分.
    • 表示非 ASCII 字元的多位元組串的第一個位元組總是在 0xC0 到 0xFD 的範圍裡, 並指出這個字元包含多少個位元組. 多位元組串的其餘位元組都在 0x80 到 0xBF 範圍裡. 這使得重新同步非常容易, 並使編碼無國界, 且很少受丟失位元組的影響.
    • 可以編入所有可能的 231
      個 UCS 代碼
    • UTF-8 編碼字元理論上可以最多到 6 個位元組長, 然而 16 位 BMP 字元最多隻用到 3 位元組長.
    • Bigendian UCS-4 位元組串的排列順序是預定的.
    • 位元組 0xFE 和 0xFF 在 UTF-8 編碼中從未用到.

    下列位元組串用來表示一個字元. 用到哪個串取決於該字元在 Unicode 中的序號.

    U-00000000 - U-0000007F: 0xxxxxxx
    U-00000080 - U-000007FF: 110xxxxx
    10xxxxxx
    U-00000800 - U-0000FFFF: 1110xxxx
    10xxxxxx
    10xxxxxx
    U-00010000 - U-001FFFFF: 11110xxx
    10xxxxxx
    10xxxxxx
    10xxxxxx
    U-00200000 - U-03FFFFFF: 111110xx
    10xxxxxx
    10xxxxxx
    10xxxxxx
    10xxxxxx
    U-04000000 - U-7FFFFFFF: 1111110x
    10xxxxxx
    10xxxxxx
    10xxxxxx
    10xxxxxx
    10xxxxxx

    xxx 的位置由字元編碼數的二進位表示的位填入. 越靠右的 x 具有越少的特殊意義. 只用最短的那個足夠表達一個字元編碼數的多位元組串. 注意在多位元組串中, 第一個位元組的開頭"1"的數目就是整個串中位元組的數目.

    例如
    : Unicode 字元 U+00A9 = 1010 1001 (著作權符號) 在 UTF-8 裡的編碼為:

    11000010 10101001 = 0xC2 0xA9

    而字元 U+2260 = 0010 0010 0110 0000 (不等於) 編碼為:

    11100010 10001001 10100000 = 0xE2 0x89 0xA0

    這種編碼的官方名字拼字為 UTF-8, 其中 UTF 代表 U
    CS T
    ransformation F
    ormat. 請勿在任何文檔中用其他名字 (比如 utf8 或 UTF_8) 來表示 UTF-8, 當然除非你指的是一個變數名而不是這種編碼本身.

    什麼程式設計語言支援 Unicode?

    在大約 1993 年之後開發的大多數現代程式設計語言都有一個特別的資料類型, 叫做 Unicode/ISO 10646-1 字元. 在 Ada95 中叫 Wide_Character, 在 Java 中叫 char.

    ISO C 也詳細說明了處理多位元組編碼和寬字元 (wide characters) 的機制, 1994 年 9 月 Amendment 1 to ISO C
    發表時又加入了更多. 這些機制主要是為各類東亞編碼而設計的, 它們比處理 UCS 所需的要健壯得多. UTF-8 是 ISO C 標準調用多位元組字串的編碼的一個例子, wchar_t
    類型可以用來存放 Unicode 字元.

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.