LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: go1640

有关 utf8 字符集的讨论请进这里!

[复制链接]
发表于 2005-3-9 01:21:47 | 显示全部楼层
楼上两位似乎都是南京大学的哦。
回复 支持 反对

使用道具 举报

发表于 2005-3-25 14:26:07 | 显示全部楼层
见识了
回复 支持 反对

使用道具 举报

发表于 2005-3-28 17:04:12 | 显示全部楼层
晕,看到这么多还是感到有点乱,有那个出来系统说一下就好了。
回复 支持 反对

使用道具 举报

发表于 2005-3-28 23:13:21 | 显示全部楼层
前面几帖的排版看得很乱
回复 支持 反对

使用道具 举报

发表于 2005-4-16 11:37:00 | 显示全部楼层
Post by ogog
楼上两位似乎都是南京大学的哦。

原来是校友啊
回复 支持 反对

使用道具 举报

发表于 2005-4-16 14:07:20 | 显示全部楼层
UTF-8 and Unicode FAQ

by Markus Kuhn
中國LINUX論壇翻譯小組 xLoneStar[譯] 2000年2月

這篇文章說明了在 POSIX 系統 (Linux,Unix) 上使用 Unicode/UTF-8 所需要的信息. 在將?聿贿h的几年里, Unicode 已經很接近于取代 ASCII 與 Latin-1 編碼的位置了. 它不僅允許你處理處理事?上存在于地球上的任何語言文字, 而且提供了一個全面的數學與技朮符號集, 因此可以簡化科學信息交換.

UTF-8 編碼提供了一種簡便而向后兼容的方法, 使得那種完全圍繞 ASCII 設計的操作系統, 比如 Unix, 也可以使用 Unicode. UTF-8 就是 Unix, Linux 已經?似的系統使用 Unicode 的方式. 現在是你了解它的時候了.
什么是 UCS 和 ISO 10646?

國際標准 ISO 10646 定義了 通用字符集 (Universal Character Set, UCS). UCS 是所有其他字符集標准的一個超集. 它保証與其他字符集是雙向兼容的. 就是說, 如果你將任何文本字符串翻譯到 UCS格式, 然后再翻譯回原編碼, 你不會?G失任何信息.

UCS 包含了用于表達所有已知語言的字符. 不僅包括拉丁語,希臘語, 斯拉夫語,希伯?碚Z,阿拉伯語,?喢滥?喺Z和喬治?喺Z的描述, 還包括中文, 日文和韓文這樣的象形文字, 以及 平假名, 片假名, 孟加拉語, 旁遮普語果魯穆奇字符(Gurmukhi), 泰米爾語, 印.埃納德語(Kannada), Malayalam, 泰國語, 老撾語, ?h語拼音(Bopomofo), Hangul, Devangari, Gujarati, Oriya, Telugu 以及其他數也數不清的語. 對于還沒有加入的語言, 由于正在研究怎樣在計算機中最好地編碼它們, 因而最終它們都將被加入. 這些語言包括 Tibetian, 高棉語, Runic(古代北歐文字), 埃塞俄比?喺Z, 其他象形文字, 以及各種各樣的印-歐語系的語言, 還包括挑選出?淼乃嚃X語言比如 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 以外的字符都屬于非常特殊的字符(比如象形文字), 且只有專家在歷史和科學領域里才會用到它們. 按當前的計划, 將?硪苍S再也不會有字符被分配到? 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 字符 (一種特別的, 更加?碗s的韓國文的編碼, 使用兩個或三個子字符?砭幋a一個韓文音?)
級別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 標准的碼表兼容, 并緊密地共同調整任何未?淼臄U展.
那么 Unicode 和 ISO 10646 不同在什么地方?

Unicode 協會公布的 Unicode 標准 嚴密地包含了 ISO 10646-1 ?現級別3的基本多語言面. 在兩個標准里所有的字符都在相同的位置并且有相同的名字.

Unicode 標准額外定義了許多與字符有關的語義符號學, 一般而言是對于?現高質量的印刷出版系統的更好的參考. Unicode 詳細說明了繪制某些語言(比如阿拉伯語)表達形式的算法, 處理雙向文字(比如拉丁與希伯?砦幕旌衔淖)的算法和 排序與字符串比較 所需的算法, 以及其他許多東西.

另一方面, ISO 10646 標准, 就象?V為人知的 ISO 8859 標准一樣, 只不過是一個簡單的字符集表. 它指定了一些與標准有關的朮語, 定義了一些編碼的別名, 并包括了規范說明, 指定了怎樣使用 UCS 連接其他 ISO 標准的?現, 比如 ISO 6429 和 ISO 2022. 還有一些與 ISO 緊密相關的, 比如 ISO 14651 是關于 UCS 字符串排序的.

考慮到 Unicode 標准有一個易記的名字, 且在任何好的書店里的 Addison-Wesley 里有, 只花費 ISO 版本的一小部分, 且包括更多的輔助信息, 因而它成為使用?V泛得多的參考也就不足為奇了. 然而, 一般認為, 用于打印 ISO 10646-1 標准的字體在某些方面的質量要高于用于打印 Unicode 2.0的. 專業字體設計者總是被建議說要兩個標准都?現, 但一些提供的樣例字形有顯著的區別. ISO 10646-1 標准同樣使用四種不同的風格變體?盹@示表意文字如中文, 日文和韓文 (CJK), 而 Unicode 2.0 的表里只有中文的變體. 這導致了普遍的認為 Unicode 對日本用戶?碚f是不可接收的傳說, 盡管是錯誤的.
什么是 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 范圍里. 這使得重新同步非常容易, 并使編碼無國界, 且很少受?G失字?的影響.
    * 可以編入所有可能的 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 代表 UCS Transformation Format. 請勿在任何文檔中用其他名字 (比如 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 發表時又加入了更多. 這些機制主要是為各?東?喚幋a而設計的, 它們比處理 UCS 所需的要健壯得多. UTF-8 是 ISO C 標准調用多字?字符串的編碼的一個例子, wchar_t ?型可以用?泶娣 Unicode 字符.
在 Linux 下該如何使用 Unicode?

在 UTF-8 之前, 不同地區的 Linux 用戶使用各種各樣的 ASCII 擴展. 最普遍的歐洲編碼是 ISO 8859-1 和 ISO 8859-2, 希臘編碼 ISO 8859-7, 俄國編碼 KOI-8, 日本編碼 EUC 和 Shift-JIS, 等等. 這使得 文件的交換非常困難, 且應用軟件必須特別關心這些編碼的不同之處.

最終, Unicode 將取代所有這些編碼, 主要通過 UTF-8 的形式. UTF-8 將應用在

    * 文本文件 (源代碼, HTML 文件, email 消息, 等等)
    * 文件名
    * 標准輸入與標准輸出, 管道
    * 環境變量
    * 剪切與粘貼選擇?沖區
    * telnet, modem 和到終端模擬器的串口連接
    * 以及其他地方以前用ASCII?肀硎镜淖止?串

在 UTF-8 模式下, 終端模擬器, 比如 xterm 或 Linux console driver, 將每次按鍵轉換成相應的 UTF-8 串, 然后發送到前台進程的 stdin 里. ?似的, 任何進程在 stdout 上的輸出都將發送到終端模擬器, 在那里用一個 UTF-8 解碼器進行處理, 之后再用一種 16 位的字體顯示出?.

只有在功能完善的多語言字處理器包里才可能有完全的 Unicode 功能支持. 而?V泛用在 Linux 里用于取代 ASCII 和其他 8 位字符集的方案則要簡單得多. 第一步, Linux 終端模擬器和命令行工具將只是轉變到 UTF-8. 這意味著只用到 級別1 的 ISO 10646-1 ?現 (沒有組合字符), 且只支持那些不需要更多處理的語言象 拉丁, 希臘, 斯拉夫 和許多科學用符號. 在這個級別上, UCS 支持與 ISO 8859 支持?似, 唯一顯著的區別是現在我們有几千種字符可以用了, 其中的字符可以用多字?串?肀硎.

總有一天 Linux 會當然地支持組合字符, 但即便如此, 對于組合字符串, 預作字符(如何可用的話)仍將是首選的. 更正式地, 在 Linux 下用 Unicode 對文本編碼的首選的方法應該是定義在 Unicode Technical Report #15 里的 Normalization Form C.

在今后的一個階段, 人們可以考慮增加在日文和中文里用到的雙字?字符的支持 (他們相對比較簡單), 組合字符支持, 甚至也許對?挠抑磷髸鴮懙恼Z言如希伯?砦 (他們可不是那么簡單的) 的支持. 但對這些高級功能的支持不應該阻礙簡單的平板 UTF-8 在 拉丁, 希臘, 斯拉夫和科學用符號方面的快速應用, 以取代大量的歐洲 8 位編碼, 并提供一個象樣的科學用符號集.
我該怎樣修改我的軟件?

有兩種途?娇梢灾С UTF-8, 我稱之為軟轉換與硬轉換. 軟轉換時, 各處的數據均保存為 UTF-8 形式, 因而需要修改的軟件很少. 在硬轉換時, 程序將讀入的 UTF-8 數據轉換成寬字符數組, 以在應用程序內部處理. 在輸出時, 再把字符串轉換回 UTF-8 形式.

大多數應用程序只用軟轉換就可以工作得很好了. 這使得將 UTF-8 引入 Unix 成為切?可行的. 例如, 象 cat 和 echo 這樣的程序根本不需要修改. 他們仍然可以對輸入輸出的是 ISO 8859-2 還是 UTF-8 一無所知, 因為它們只是搬運字?流而沒有處理它們. 它們只能識別 ASCII 字符和象 '\n' 這樣的控制碼, 而這在 UTF-8 下也沒有任何改變. 因此, 這些應用程序的 UTF-8 編碼與解碼將完全在終端模擬器里完成.

而那些通過數字?數?慝@知字符數量的程序則需要一些小修改. 在 UTF-8 模式下, 它們必須不數入 0x80 到 0xBF 范圍內的字?, 因為這些只是跟隨字?, 它們本身并不是字符. 例如, ls 程序就必須要修改, 因為它通過數文件名中字符數?砼欧沤o用戶的目錄表格布局. ?似地, 所有的假定其輸出為定寬字體, 并因此而格式化它們的程序, 必須學會怎樣數 UTF-8 文本中的字符數. 編輯器的功能, 如刪除單個字符, 必須要作輕微的修改, 以刪除可能屬于該字符的所有字?. 受影響有編輯器 (vi,emacs, 等等)以及使用 ncurses 庫的程序.

Linux 核心使用軟轉換也可以工作得很好, 只需要非常微小的修改以支持 UTF-8. 大多數處理字符串的核心功能 (例如: 文件名, 環境變量, 等等) 都不受影響. 下列地方也許必須修改:

    * 控制台顯示與鍵盤驅動程序 (另一個 VT100 模擬器) 必須能編碼和解碼 UTF-8, 必須要起碼支持 Unicode 字符集的几個子集. ? Linux 1.2 起這些功能已經有了.
    * 外部文件系統驅動程序, 例如 VFAT 和 WinNT 必須轉換文件名字符編碼. UTF-8 已經加入可用的轉換選項的列表里了, 因此 mount 命令必須告訴核心驅動程序用戶進程希望看到 UTF-8 文件名. 既然 VFAT 和 WinNT 無論如何至少已經用了 Unicode了, 那么 UTF-8 在這里就可以發揮其優勢, 以保証轉換中無信息損失.
    * POSIX 系統的 tty 驅動程序支持一種 "cooked" 模式, 有一些原始的行編輯功能. 為了讓字符刪除功能工作正常, stty 必須在 tty 驅動程序里設置 UTF-8 模式, 因此它就不會把 0x80 到 0xBF 范圍內的跟隨字符也數進去了. Bruno Haible 那里已經有了一些 stty 和核心 tty 驅動 程序的 Linux 補丁 了.

C 對 Unicode 和 UTF-8 的支持

? GNU glibc 2.1 開始, wchar_t ?型已經正式定為只存放獨立于當前 locale 的, 32位的 ISO 10646 值. glibc 2.2 開始將完全支持 ISO C 中的多字?轉換函數 (wprintf(),mbstowcs(),等等), 這些函數可以用于在 wchar_t 和包括 UTF-8 在內的任何依賴于 locale 的多字?編碼間進行轉換.

例如, 你可以寫

  wprintf(L"Sch?e Gr?e!\n");

然后, 你的軟件將按照你的用戶在環境變量 LC_CTYPE (例如, en_US.UTF-8 或 de_DE.ISO_8859-1) 中選擇的 locale 所指定的編碼?泶蛴∵@段文字. 你的編譯器必須運行在與該 C 源文件所用編碼相應的 locale 中, 在目標文件中以上的寬字符串將改為 wchar_t 字符串存儲. 在輸出時, 運行時庫將把 wchar_t 字符串轉換回與程序執行時的 locale 相應的編碼.

注意, ?似這樣的操作:

  char c = L"a";

只允許? U+0000 到 U+007F (7 位 ASCII) 范圍里的字符. 對于非 ASCII 字符, 不能直接? wchar_t 到 char 轉換.

現在, 象 readline() 這樣的函數在 UTF-8 locale 下也能工作了.
怎樣激活 UTF-8 模式?

如果你的應用程序既支持 8 位字符集 (ISO 8859-*,KOI-8,等等), 也支持 UTF-8, 那么它必須通過某種方法以得知是否應使用 UTF-8 模式. 幸運的是, 在未?淼募改昀, 人們將只使用 UTF-8, 因此你可以將它作為默認, 但即使如此, 你還是得既支持傳統 8 位字符集, 也支持 UTF-8.

當前的應用程序使用許許多多的不同的命令行開關?砑せ钏鼈兏髯缘 UTF-8 模式, 例如:

    * xterm 命令行選項 "-u8" 和 X resource "XTerm*utf8:1"
    * gnat/gcc 命令行選項 "-gnatW8"
    * stty 命令行選項 "iutf8"
    * mined 命令行選項 "-U"
    * xemacs elisp 包裹 以在 UTF-8 和內部使用的 MULE 編碼間轉換
    * vim 'fileencoding' 選項
    * less 環境變量 LESSCHARSET=utf-8

記住每一個應用程序的命令行選項或其他配置方法是非常單調乏味的, 因此急需某種標准方法.

如果你在你的應用程序里使用硬轉換, 并使用某種特定的 C 庫函數?硖幚硗獠孔址幋a和內部使用的 wchar_t 編碼的轉換工作, 那么 C 庫會幫你處理模式切換的問題. 你只需將環境變量 LC_CTYPE 設為正確的 locale, 例如, 如果你使用 UTF-8, 那就是en.UTF-8, 而如果是 Latin-1, 并需要英語的轉換, 則設為 en.ISO_8859-1.

然而, 大多數現存軟件的維護者選擇用軟轉換?泶, 而不使用 libc 的寬字符函數, 不僅因為它們還未得到?V泛應用, 還因為這會使得軟件進行大規模修改. 在這種情況下, 你的應用程序必須自己?慝@知何時使用 UTF-8 模式. 一種方式是做以下工作:

按照環境變量 LC_ALL, LC_CTYPE, LANG 的順序, 尋找第一個有值的變量. 如果該值包含 UTF-8 子串 (也許是小寫或沒有"-") 則默認為 UTF-8 模式 (仍然可以用命令行開關?碇卦O), 因為這個值可靠又恰當地指示了 C 庫應該使用一種 UTF-8 locale.

提供一個命令行選項 (或者如果是 X 客戶程序則用 X resource 的值) 將仍然是有用的, 可以用?碇卦O由 LC_CTYPE 等環境變量指定的默認值.
我怎樣才能得到 UTF-8 版本的 xterm?

在 XFree86 里帶的 xterm 版本最近已經由 Thomas E. Dickey 加入了支持 UTF-8 的擴展. 使用方法是, 獲取 xterm patch #119 (1999-10-16) 或更新版本, 用 "./configure --enable-wide-chars ; make" ?砭幾g, 然后用命令行選項 -u8 ?碚{用 xterm, 使它將輸入輸出轉換為 UTF-8. 在 UTF-8 模式里使用一個 *-ISO10646-1 字體. 當你在 ISO 8859-1 模式里時也可以使用 *-ISO10646-1 字體, 因為 ISO 10646-1 字體與 ISO 8859-1 字體是完全向后兼容的.

新的支持 UTF-8 的 xterm 版本, 以及一些 ISO 10646-1 字體, 將被收錄入 XFree86 4.0 版里.
xterm 支持組合字符嗎?

Xterm 當前只支持級別1的 ISO 10646-1, 就是說, 不提供組合字符的支持. 當前, 組合字符將被當作空格字符對待. xterm 將?淼男抻啺婧苡锌赡芗尤肽承┖唵蔚慕M合字符支持, 就是僅僅將那個有一個或多個組合字符的基字符加粗 (logical OR-ing). 對于在基線以下的和在小字符上方的重音符?碚f, 這樣處理的結果還是可以接受的. 對于象泰國文字體那樣使用特別設計的加粗字符的文字, 這樣處理也能工作的很好. 然而, 對于某些字體里, 在較高的字符上方組合上的重音符, 特別是對于 "fixed" 字體族, 產生的結果就不完全令人?M意了. 因此, 在可用的地方, 應該繼續優先使用預作字符.
xterm 支持半寬與全寬 CJK 字體嗎?

Xterm 當前只支持那種所有字形都等寬的 cell-spaced 的字體. 將?淼男抻啺婧苡锌赡転 CJK 語言加入半寬與全寬字符支持, ?似于 kterm 提供的那種. 如果選擇的普通字體是 X×Y 象素大小, 且寬字符模式是打開的, 那么 xterm 會試圖裝入另外的一個 2X×Y 象素大小的字體 (同樣的 XLFD, 只是 AVERAGE_WIDTH 屬性的值翻倍). 它會用這個字體?盹@示所有在 Unicode Technical Report #11 里被分配了East Asian Wide (W) 或 East Asian FullWidth (F) 寬度屬性的 Unicode 字符. 下面這個 C 函數用?頊y試一個 Unicode 字符是否是寬字符并需要用覆蓋兩個字符單元的字形?盹@示:

  /* This function tests, whether the ISO 10646/Unicode character code
   * ucs belongs into the East Asian Wide (W) or East Asian FullWidth
   * (F) category as defined in Unicode Technical Report #11. In this
   * case, the terminal emulator should represent the character using a
   * a glyph from a double-wide font that covers two normal (Latin)
   * character cells. */

  int iswide(int ucs)
  {
    if (ucs < 0x1100)
      return 0;

    return
      (ucs >= 0x1100 && ucs <= 0x115f) || /* Hangul Jamo */
      (ucs >= 0x2e80 && ucs <= 0xa4cf && (ucs & ~0x0011) != 0x300a &&
       ucs != 0x303f) ||                     /* CJK ... Yi */
      (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
      (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
      (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
      (ucs >= 0xff00 && ucs <= 0xff5f) || /* Fullwidth Forms */
      (ucs >= 0xffe0 && ucs <= 0xffe6);
  }

某些 C 庫也提供了函數

  #include <wchar.h>
  int wcwidth(wchar_t wc);
  int wcswidth(const wchar_t *pwcs, size_t n);

用?頊y定該寬字符 wc 或由 pwcs 指向的字符串中的 n 個寬字符碼 (或者少于 n 個寬字符碼, 如果在 n 個寬字符碼之前遇到一個空寬字符的話) 所要求的列位置的數量. 這些函數定義在 Open Group 的 Single UNIX Specification 里. 一個拉丁/希臘/斯拉夫/等等的字符要求一個列位置, 一個 CJK 象形文字要求兩個, 而一個組合字符要求零個.
最終 xterm 是否會支持?挠业阶蟮臅鴮?

此刻還沒有給 xterm 增加?挠业阶蠊δ艿挠嫽. 希伯?砼c阿拉伯用戶因此不得不靠應用程序在將希伯?砦呐c阿拉伯文字符串送到終端前按左方向翻轉它們, 換句話說, 雙向處理必須在應用程序里完成, 而不是在 xterm 里. 至少, 希伯?砼c阿拉伯文在預作字形的可用性的形式上, 以及提示表格上的支持, 比 ISO 8859 要有所改進. 現在還遠沒有決定 xterm 是否支持雙向文字以及該怎樣工作. ISO 6429 = ECMA-48 和 Unicode bidi algorithm 都提供了可供選擇的開始點. 也可以參考 ECMA Technical
Report TR/53. Xterm 也不處理阿拉伯文, Hangul 或 印度文本的格式化算法, 而且現在還不太清楚在 VT100 模擬器里處理是否可行和值得, 或者應該留給應用軟件去處理. 如果你打算在你的應用程序里支持雙向文字輸出, 看一下 FriBidi, Dov Grobgeld 的 Unicode 雙向算法的自由?現.
我在哪兒能找到 ISO 10646-1 X11 字體?

在過去的几個月里出現了相當多的 X11 的 Unicode 字體, 并且還在快速增多.

    * Markus Kuhn 正和其他許多志愿者一起工作于手動將舊的 -misc-fixed-*-iso8859-1 字體擴展到覆蓋所有的歐洲字符表 (拉丁, 希臘, 斯拉夫, 國際音標字母表. 數學與技朮符號, 某些字體里甚至有?喢滥?喺Z, 喬治?喺Z, 片假名等). 更多信息請參考 Unicode fonts and tools for X11 頁. 這些字體將與 XFree86 一起分發. 例如字體

  -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1

      (舊的 xterm 的 fixed 缺省字體的一個擴展, 包括超過 3000 個字符) 已經是 XFree86 3.9 snapshot 的一部分了.

    * Markus 也做好了 X11R6.4 distribution 里所有的 Adobe 和 B&H BDF 字體的 ISO 10646 版本. 這些字體已經包含了全部 Postscript 字體表 (大約 30 個額外的字符, 大部分也被 CP1252 MS-Windows 使用, 如 smart quotes, dashes 等), 在 ISO 8859-1 編碼下是沒有的. 它們在 ISO 10646-1 版本里是完全可用的.
    * XFree86 4.0 將攜帶一個集成的 TrueType 字體引擎, 這使得你的 X 應用程序可以將任何 Apple/Microsoft 字體用于 ISO 10646-1 編碼.
    * 將?淼 XFree86 版本很有可能?姆职l版中去除大多數舊的 BDF 字體, 取而代之的是 ISO 10646-1 編碼的版本. X 服務器則會增加一個自動編碼轉換器, 只有當舊的 8 位軟件請求一個?似于 ISO 8859-* 編碼的字體時, 才虛擬地? ISO 10646-1 字體文件中創建一個這樣的字體. 現代軟件應該優先地直接使用 ISO 10646-1 字體編碼.
    * ClearlyU (cu12) 是一個非常有用的 X11 的 12 點陣, 100 dpi 的 proportional ISO 10646-1 BDF 字體, 包含超過 3700 個字符, 由 Mark Leisher 提供 (樣例圖象).
    * Roman Czyborra 的 GNU Unicode font 項目工作于收集一個完整的與免費的 8×16/16×16 pixel Unicode 字體. 目前已經覆蓋了 34000 個字符.
    * etl-unicode 是一個 ISO 10646-1 BDF 字體, 由 Primoz Peterlin 提供.

Unicode X11 字體名字以 -ISO10646-1 結尾. 這個 X 邏輯字體描述器 (X Logical Font Descriptor, XLFD) 的 CHARSET_REGISTRY 和 CHARSET_ENCODING 域里的值已經為所有 Unicode 和 ISO 10646-1 的 16 位字體而正式地注冊了. 每個 *-ISO10646-1 字體都包含了整個 Unicode 字符集里的某几個子集, 而用戶必須弄清楚他們選擇的字體覆蓋哪几個他們需要的字符子集.

*-ISO10646-1 字體通常也指定一個 DEFAULT_CHAR 值, 指向一個非 Unicode 字形, 用?肀硎舅性谠撟煮w里不可用的字符 (通常是一個虛線框, 一個 H 的大小, 位于 0x1F 或 0xFFFE). 這使得用戶至少能知道這兒有一個不支持的字符. xterm 用的小的定寬字體比如 6x13 等, 將永遠無法覆蓋所有的 Unicode, 因為許多文字比如日本?h字只能用比歐洲用戶?V泛使用的大的象素尺寸才能表示. 歐洲使用的典型的 Unicode 字體將只包含大約 1000 到 3000 個字符的子集.
我怎樣才能找出一個 X 字體里有哪些字形?

X 協議無法讓一個應用程序方便地找出一個 cell-spaced 字體提供哪些字形, 它沒有為字體提供這樣的量度. 因此 Mark Leisher 和 Erik van de Poel (Netscape) 指定了一個新的 _XFREE86_GLYPH_RANGES BDF 屬性, 告訴應用程序該 BDF 字體?現了哪個 Unicode 子集. Mark Leisher 提供了一些樣例代碼以產生并掃描這個屬性, 而 Xmbdfed 3.9 以及更高版本將自動將其加入到由它產生的每個 BDF 文件里.
與 UTF-8 終端模擬器相關的問題是什么?

VT100 終端模擬器接受 ISO 2022 (=ECMA-35) ESC 序列, 用于在不同的字符集間切換.

UTF-8 在 ISO 2022 的意義里是一個 "其他編碼系統" (參考 ECMA 35 的 15.4 ?). UTF-8 是在 ISO 2022 SS2/SS3/G0/G1/G2/G3 世界之外的, 因此如果你? ISO 2022 切換到 UTF-8, 所有的 SS2/SS3/G0/G1/G2/G3 狀態都變得沒有意義了, 直到你離開 UTF-8 并切換回 ISO 2022. UTF-8 是一個沒有國家的編碼, 也就是一個自我終結的短字?序列完全決定了它代表什么字符, 獨立于任何國家的切換. G0 與 G1 在 ISO 10646 里與在 ISO 8859-1 里相同, 而 G2/G3 在 ISO 10646 里不存在, 因為任何字符都有固定的位置, 因而不會發聲切換. 在 UTF-8 模式下, 你的終端不會因為你偶然地裝入一個二進制文件而切換入一種奇怪圖形字符模式. 這使得一個終端在 UTF-8 模式下比在 ISO 2022 模式下要健壯得多, 而且因此可以有辦法將終端鎖在 UTF-8 模式里, 而不會偶然地回到 ISO 2022 世界里.

ISO 2022 標准指定了一系列的 ESC % 序列, 以離開 ISO 2022 世界 (指定其他的編碼系統, DOCS), 用于 UTF-8 的許多這樣的序列已經注冊進了 ISO 2375 International Register of Coded Character Sets:

    * ESC %G ? ISO 2022 里激活一個未指定?現級別的 UTF-8 模式且允許再返回 ISO 2022.
    * ESC %@ ? UTF-8 回到 ISO 2022, 條件是通過 ESC %G 進入的 UTF-8
    * ESC %/G 切換進 UTF-8 級別 1 且不返回.
    * ESC %/H 切換進 UTF-8 級別 2 且不返回.
    * ESC %/I 切換進 UTF-8 級別 3 且不返回.

當一個終端模擬器在 UTF-8 模式時, 任何 ISO 2022 逃脫碼序列例如用于切換 G2/G3 等的都被忽略. 一個在 UTF-8 模式下的終端模擬器唯一會執行的 ISO 2022 序列是 ESC %@ 以? UTF-8 返回 ISO 2022 方案.

UTF-8 仍然允許你使用象 CSI 這樣的 C1 控制字符, 盡管 UTF-8 也使用 0x80-0x9F 范圍里的字?. 重要的是必須理解在 UTF-8 模式下的終端模擬器必須在執行任何控制字符前對收到的字?流運用 UTF-8 解碼器. C1 字符與其他任何大于 U+007F 的字符一樣需先經過 UTF-8 解碼.
已經有哪些支持 UTF-8 的應用程序了?

    * Yudit 是 Gaspar Sinai 的自由 X11 Unicode 編輯器
    * Mined 98 由 Thomas Wolff 提供, 是一個可以處理 UTF-8 的文本編輯器.
    * less 版本 346 或更高, 支持 UTF-8
    * C-Kermit 7.0 在傳輸, 終端, 及文件字符集方面支持 UTF-8.
    * Sam 是 Plan9 的 UTF-8 編輯器, ?似于 vi, 也可用于 Linux 和 Win32. (Plan9 是第一個完全轉向 UTF-8, 將其作為字符編碼的操作系統.)
    * 9term 由 Matty Farrow 提供, 是一個 Plan9 操作系統的 Unicode/UTF-8 終端模擬器的 Unix 移植.
    * Wily 是一個 Plan9 Acme 編輯器的 Unix ?現.
    * ucm-0.1 是 Juliusz Chroboczek 的 Unicode 字符映射表, 一個小工具, 使你可以選中任何一個 Unicode 字符并粘貼進你的應用程序.

有哪些用于改善 UTF-8 支持的補丁?

    * Robert Brady 提供了一個 patch for less 340 (現在已經合并進了 less 344)
    * Bruno Haible 提供了用于 stty, Linux 核心 tty 等的 多個補丁.
    * Otfried Cheong 編寫了 Unicode encoding for GNU Emacs 工具箱, 使 Mule 能夠處理 UTF-8 文件.

Postscript 字形的名字與 UCS 代碼是怎么關聯的?

參考 Adobe 的 Unicode and Glyph Names 指南.
X11 的剪切與粘貼工作在 UTF-8 時是如何完成的?

參考 Juliusz Chroboczek 的 客戶機間 Unicode 文本的交換 草案, 對 ICCCM 的一個擴充的建議, 用一個新的可用于屬性?型(property type)和選中(selection)目標的原子 UTF8_STRING ?硖幚 UTF-8 的選中.
現在有沒有用于處理 Unicode 的免費的庫?

    * IBM Classes for Unicode
    * Mark Leisher 的 UCData Unicode 字符屬性庫和 wchar_t 支持測試碼.

各種 X widget 對 Unicode 支持的現狀如何?

    * GScript - Unicode 與?碗s文本處理 是一個為 GTK+ 增加全功能的 Unicode 支持的項目.
    * Qt 2.0 現在支持使用 *-ISO10646-1 字體了.
    * FriBidi 是 Dov Grobgeld 的 Unicode 雙向算法的免費?現.

有什么關于這個話題的好的郵件列表?

你確?應該訂閱的是 unicode@unicode.org 郵件列表, 這是發現標准的作者和其他許多領袖的話語的最好辦法. 訂閱方法是, 用 "subscribe" 作為標題, "subscribe YOUR@EMAIL.ADDRESS unicode" 作為正文, 發一條消息到 unicode-request@unicode.org.

也有一個專注與改進通常用于 GNU/Linux 系統上應用程序的 UTF-8 支持的郵件列表 linux-utf8@nl.linux.org. 訂閱方法是, 以 "subscribe linux-utf8" 為內容, 發送消息到 majordomo@nl.linux.org. 你也可以瀏覽 linux-utf8 archive

其他相關的還有 XFree86 組的 "字體" 與 "i18n" 列表, 但你必須成為一名正式的開發者才能訂閱.
回复 支持 反对

使用道具 举报

发表于 2005-4-16 14:10:56 | 显示全部楼层
回复 支持 反对

使用道具 举报

发表于 2005-4-16 14:37:41 | 显示全部楼层
基础建设版的几篇帖子讲得都不错
http://www.linuxsir.cn/bbs/showthread.php?t=34400

http://www.linuxsir.cn/bbs/showthread.php?t=78155   字体基础和底层知识(多帖合并)


http://www.linuxsir.cn/bbs/showthread.php?t=177421

对字符编码与Unicode,ISO 10646,UCS,UTF8,UTF16,GBK,GB2312的理解
转自 Donews Blog [ http://www.donews.net ]
-------------------------------

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 代表 UCS Transformation Format. 请勿在任何文档中用其他名字 (比如 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 字符.


http://www.linuxsir.cn/bbs/showthread.php?t=16690   LFS 版面的一篇简述

http://www.linuxsir.cn/bbs/showthread.php?t=106415   有关前段时间内核的 cp936 码表出错的问题 by stoneme


其实比较好的文档还是在 freebsdchina 网站

http://www.linuxsir.cn/bbs/showthread.php?t=179032
QUOTE=jhuangjiahua
[15:46] <sunmoon1997> locale 不重要
[15:46] <minghua> http://plateauwolf.blogspot.com/ ... #111146290739576975
[15:47] <sunmoon1997> 支持相应的编码方式就行。。
[15:47] <Huahua> 恩
[15:47] <minghua> 我在 blog 里面说的比较偏激,但基本意思是一样的
[15:48] <caiqian> minghua: 嗯,大概已经被封了
[15:48] <sunmoon1997> 没有必要去炒作 locale
[15:48] <minghua> Err...
[15:49] <minghua> 有人有兴趣吗?有的话我就贴一下
[15:49] <caiqian> minghua: 有啊
[15:49] <minghua> Monday, March 21, 2005
[15:49] <minghua> 中文编码和 Unicode
[15:49] <sunmoon1997> 包括 gb18030 都是过渡性标准
[15:49] <minghua> 最近 Debian 的中文邮件列表非常的热闹,使得我这个 moderator 一时都忙不过来。有一个主题是在讨论应不应该统一使用 UTF-8 编码,说的也没有什么新意。倒是今天的另外一个主题中提到中国信息技术标准化技术委员会对于 GB18030 和 Unicode 的介绍,发现里面居然说 ISO10646 和 Unicode 是两个不同的标准,十分吃惊。自己在网上找
[15:49] <minghua> 了一下资料,才知道自己的理解基本没有错,而国内这些人真是极尽颠倒黑白之能事,一定要往自己脸上贴金
[15:50] <minghua> Wikipedia 里面关于 ISO10646 的介绍还是很详细的。大体说来就是早期的 ISO10646 设计上有重大问题,和 ASCII 兼容不好,效率又低,得不到众多厂商的支持。后来不得不和各厂商联合成立的 Unicode 组织协调,把 ISO10646 做了很大的改变。现在所说的 ISO10646,已经和 Unicode 基本上是一码事了,只不过 ISO10646 是一个纯粹的字符映射,而
[15:50] <minghua> Unicode 还有一些针对各种语言的特殊规则,比如从右到左的书写,一个字符(character)对应多个字形(glyph)的情况。
[15:50] <minghua> 那么为什么中国信息技术标准化技术委员会要把那个已经被废弃的老 ISO10646 标准拿出来说事儿呢?这就要翻翻老皇历了。Wikipedia 对于这种没人用的标准自然语焉不详,只好再找。好在有 UTF-1 这个听都没听说过的关键词,结果找到一篇技术细节很清楚的文章。读了之后才明白,原来这个老 ISO10646 就是中国人为主制定的,在
[15:50] <minghua> 中国叫做 GB13000(这个我早就听说过,一直也不明白到底是什么东西),其核心就是要和 GB2312 和 GBK 兼容,采用两字节的编码,根本不管其它拉丁文字方不方便,更不要说阿拉伯什么国家的文字了。再加上 UTF-1 这个失败的和 ASCII 兼容的转换方式,有厂商支持才怪。
[15:50] <minghua> 现在 ISO10646 实际已经和 Unicode 并轨了,国内的人还把 ISO10646 单独提出来,无非就是要说中国曾经在 ISO10646 的制定中起到重要的作用(好作用还是坏作用就不说了)。技术委员会的那篇文章,明明是介绍已经和 Unicode 并轨以后的 ISO10646(仔细看来 GB13000 实际上也是接受了 Unicode 的分区方法的),还硬要说是和 Unicode 不同,而
[15:50] <minghua> 且把 Unicode 对 ISO10646 的改进说得好象是 ISO10646 的原创,Unicode“和 ISO10646 兼容”,真是恬不知耻。
[15:50] <minghua> 现在国内还有人声称 GB18030 比 Unicode 好,让人听了真是寒心。从兼容的角度来说,GB18030 倒不失为一种选择,但毕竟只注重和旧标准兼容,不顾国际标准,不是长久之计。至于硬是要编出一些名目来把本质上是旧标准扩充的 legacy encoding 说成是最先进的技术,还通过行政手段强行推广,就不知道有没有更险恶的内幕了。
[15:50] <minghua> 重申一下:<minghua> 但是纯粹是我个人意见,不想和任何人争论
[15:51] <sunmoon1997> 包括 gb18030 都是过渡性标准
[15:51] <minghua> 补几个贴不过来的 link:
[15:51] <minghua> http://lists.debian.org/debian-chinese-gb/2005/03/msg00323.html
[15:51] <minghua> http://en.wikipedia.org/wiki/ISO10646
[15:52] <minghua> http://czyborra.com/utf/#UTF-1


-

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

发表于 2006-7-15 21:15:43 | 显示全部楼层
现在最简单的做法就是LINIX全局用UTF-8,,存的文件内容用 GBK编码,

存在 LINUX的文件系统里,还是存在用utf8 参数挂载的 FAT32 里,根本不用管这个问题,LINUX自动会转换。
回复 支持 反对

使用道具 举报

发表于 2006-7-16 21:33:06 | 显示全部楼层
所有Unix和Linux用locale来设置系统就是不科学,怎么不学一下microsoft统一使用UTF-16来实现呢???
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表