?? utf-8 and unicode faq.htm
字號:
它們在 文件名和其他 C 庫函數參數里都有特別的含義. 另外, 大多數使用 ASCII 文件的 UNIX 下的工具, 如果不進行重大修改是無法讀取 16
位的字符的. 基于這些原因, 在文件名, 文本文件, 環境變量等地方, <STRONG>UCS-2</STRONG> 不適合作為 <STRONG><B
style="COLOR: black; BACKGROUND-COLOR: #ffff66">Unicode</B></STRONG> 的外部編碼.</P>
<P>在 ISO 10646-1 <A
href="http://www.cl.cam.ac.uk/~mgk25/ucs/ISO-10646-UTF-8.html">Annex R</A> 和 <A
href="ftp://ftp.funet.fi/mirrors/nic.nordu.net/rfc/rfc2279.txt">RFC 2279</A>
里定義的 <STRONG>UTF-8</STRONG> 編碼沒有這些問題. 它是在 Unix 風格的操作系統下使用 <B
style="COLOR: black; BACKGROUND-COLOR: #ffff66">Unicode</B> 的明顯的方法.</P>
<P>UTF-8 有一下特性:
<UL>
<LI>UCS 字符 U+0000 到 U+007F (ASCII) 被編碼為字節 0x00 到 0x7F (ASCII 兼容). 這意味著只包含 7 位
ASCII 字符的文件在 ASCII 和 UTF-8 兩種編碼方式下是一樣的.
<LI>所有 >U+007F 的 UCS 字符被編碼為一個多個字節的串, 每個字節都有標記位集. 因此, ASCII 字節 (0x00-0x7F)
不可能作為任何其他字符的一部分.
<LI>表示非 ASCII 字符的多字節串的第一個字節總是在 0xC0 到 0xFD 的范圍里, 并指出這個字符包含多少個字節. 多字節串的其余字節都在
0x80 到 0xBF 范圍里. 這使得重新同步非常容易, 并使編碼無國界, 且很少受丟失字節的影響.
<LI>可以編入所有可能的 2<SUP>31</SUP>個 UCS 代碼
<LI>UTF-8 編碼字符理論上可以最多到 6 個字節長, 然而 16 位 BMP 字符最多只用到 3 字節長.
<LI>Bigendian UCS-4 字節串的排列順序是預定的.
<LI>字節 0xFE 和 0xFF 在 UTF-8 編碼中從未用到. </LI></UL>
<P>下列字節串用來表示一個字符. 用到哪個串取決于該字符在 <B
style="COLOR: black; BACKGROUND-COLOR: #ffff66">Unicode</B> 中的序號.</P>
<DIV align=center>
<CENTER>
<TABLE border=1>
<TBODY>
<TR>
<TD>U-00000000 - U-0000007F: </TD>
<TD>0<I>xxxxxxx</I> </TD></TR>
<TR>
<TD>U-00000080 - U-000007FF: </TD>
<TD>110<I>xxxxx</I> 10<I>xxxxxx</I> </TD></TR>
<TR>
<TD>U-00000800 - U-0000FFFF: </TD>
<TD>1110<I>xxxx</I> 10<I>xxxxxx</I> 10<I>xxxxxx</I> </TD></TR>
<TR>
<TD>U-00010000 - U-001FFFFF: </TD>
<TD>11110<I>xxx</I> 10<I>xxxxxx</I> 10<I>xxxxxx</I> 10<I>xxxxxx</I> </TD></TR>
<TR>
<TD>U-00200000 - U-03FFFFFF: </TD>
<TD>111110<I>xx</I> 10<I>xxxxxx</I> 10<I>xxxxxx</I> 10<I>xxxxxx</I>
10<I>xxxxxx</I> </TD></TR>
<TR>
<TD>U-04000000 - U-7FFFFFFF: </TD>
<TD>1111110<I>x</I> 10<I>xxxxxx</I> 10<I>xxxxxx</I> 10<I>xxxxxx</I>
10<I>xxxxxx</I> 10<I>xxxxxx</I> </TD></TR></TBODY></TABLE></CENTER></DIV>
<P>xxx 的位置由字符編碼數的二進制表示的位填入. 越靠右的 x 具有越少的特殊意義. 只用最短的那個足夠表達一個字符編碼數的多字節串. 注意在多字節串中,
第一個字節的開頭"1"的數目就是整個串中字節的數目.</P>
<P><STRONG>例如</STRONG>: <B
style="COLOR: black; BACKGROUND-COLOR: #ffff66">Unicode</B> 字符 U+00A9 = 1010
1001 (版權符號) 在 UTF-8 里的編碼為:</P>
<BLOCKQUOTE>
<P>11000010 10101001 = 0xC2 0xA9</P></BLOCKQUOTE>
<P>而字符 U+2260 = 0010 0010 0110 0000 (不等于) 編碼為:</P>
<BLOCKQUOTE>
<P>11100010 10001001 10100000 = 0xE2 0x89 0xA0</P></BLOCKQUOTE>
<P>這種編碼的官方名字拼寫為 UTF-8, 其中 UTF 代表 <STRONG>U</STRONG>CS
<STRONG>T</STRONG>ransformation <STRONG>F</STRONG>ormat. 請勿在任何文檔中用其他名字 (比如 utf8
或 UTF_8) 來表示 UTF-8, 當然除非你指的是一個變量名而不是這種編碼本身.</P>
<H2>什么編程語言支持 <B
style="COLOR: black; BACKGROUND-COLOR: #ffff66">Unicode</B>?</H2>
<P>在大約 1993 年之后開發的大多數現代編程語言都有一個特別的數據類型, 叫做 <B
style="COLOR: black; BACKGROUND-COLOR: #ffff66">Unicode</B>/ISO 10646-1 字符. 在
Ada95 中叫 Wide_Character, 在 Java 中叫 char.</P>
<P>ISO C 也詳細說明了處理多字節編碼和寬字符 (wide characters) 的機制, 1994 年 9 月 <A
href="http://www.lysator.liu.se/c/na1.html">Amendment 1 to ISO C</A> 發表時又加入了更多.
這些機制主要是為各類東亞編碼而設計的, 它們比處理 UCS 所需的要健壯得多. UTF-8 是 ISO C 標準調用多字節字符串的編碼的一個例子,
<EM>wchar_t</EM> 類型可以用來存放 <B
style="COLOR: black; BACKGROUND-COLOR: #ffff66">Unicode</B> 字符.</P>
<H2>在 Linux 下該如何使用 <B
style="COLOR: black; BACKGROUND-COLOR: #ffff66">Unicode</B>?</H2>
<P>在 UTF-8 之前, 不同地區的 Linux 用戶使用各種各樣的 ASCII 擴展. 最普遍的歐洲編碼是 ISO 8859-1 和 ISO
8859-2, 希臘編碼 ISO 8859-7, 俄國編碼 KOI-8, 日本編碼 EUC 和 Shift-JIS, 等等. 這使得 文件的交換非常困難,
且應用軟件必須特別關心這些編碼的不同之處.</P>
<P>最終, <B style="COLOR: black; BACKGROUND-COLOR: #ffff66">Unicode</B> 將取代所有這些編碼,
主要通過 UTF-8 的形式. UTF-8 將應用在
<UL>
<LI>文本文件 (源代碼, HTML 文件, email 消息, 等等)
<LI>文件名
<LI>標準輸入與標準輸出, 管道
<LI>環境變量
<LI>剪切與粘貼選擇緩沖區
<LI>telnet, modem 和到終端模擬器的串口連接
<LI>以及其他地方以前用ASCII來表示的字節串 </LI></UL>
<P>在 UTF-8 模式下, 終端模擬器, 比如 xterm 或 Linux console driver, 將每次按鍵轉換成相應的 UTF-8 串,
然后發送到前臺進程的 stdin 里. 類似的, 任何進程在 stdout 上的輸出都將發送到終端模擬器, 在那里用一個 UTF-8 解碼器進行處理,
之后再用一種 16 位的字體顯示出來.</P>
<P>只有在功能完善的多語言字處理器包里才可能有完全的 <B
style="COLOR: black; BACKGROUND-COLOR: #ffff66">Unicode</B> 功能支持. 而廣泛用在 Linux
里用于取代 ASCII 和其他 8 位字符集的方案則要簡單得多. 第一步, Linux 終端模擬器和命令行工具將只是轉變到 UTF-8. 這意味著只用到 級別1
的 ISO 10646-1 實現 (沒有組合字符), 且只支持那些不需要更多處理的語言象 拉丁, 希臘, 斯拉夫 和許多科學用符號. 在這個級別上, UCS
支持與 ISO 8859 支持類似, 唯一顯著的區別是現在我們有幾千種字符可以用了, 其中的字符可以用多字節串來表示.</P>
<P>總有一天 Linux 會當然地支持組合字符, 但即便如此, 對于組合字符串, 預作字符(如何可用的話)仍將是首選的. 更正式地, 在 Linux 下用
<B style="COLOR: black; BACKGROUND-COLOR: #ffff66">Unicode</B> 對文本編碼的首選的方法應該是定義在
<A href="http://www.unicode.org/unicode/reports/tr15/"><B
style="COLOR: black; BACKGROUND-COLOR: #ffff66">Unicode</B> Technical Report
#15</A> 里的 <EM>Normalization Form C.</EM></P>
<P>在今后的一個階段, 人們可以考慮增加在日文和中文里用到的雙字節字符的支持 (他們相對比較簡單), 組合字符支持, 甚至也許對從右至左書寫的語言如希伯來文
(他們可不是那么簡單的) 的支持. 但對這些高級功能的支持不應該阻礙簡單的平板 UTF-8 在 拉丁, 希臘, 斯拉夫和科學用符號方面的快速應用,
以取代大量的歐洲 8 位編碼, 并提供一個象樣的科學用符號集.</P>
<H2>我該怎樣修改我的軟件?</H2>
<P>有兩種途徑可以支持 UTF-8, 我稱之為軟轉換與硬轉換. 軟轉換時, 各處的數據均保存為 UTF-8 形式, 因而需要修改的軟件很少. 在硬轉換時,
程序將讀入的 UTF-8 數據轉換成寬字符數組, 以在應用程序內部處理. 在輸出時, 再把字符串轉換回 UTF-8 形式.</P>
<P>大多數應用程序只用軟轉換就可以工作得很好了. 這使得將 UTF-8 引入 Unix 成為切實可行的. 例如, 象 cat 和
<SAMP>echo</SAMP> 這樣的程序根本不需要修改. 他們仍然可以對輸入輸出的是 ISO 8859-2 還是 UTF-8 一無所知,
因為它們只是搬運字節流而沒有處理它們. 它們只能識別 ASCII 字符和象 '\n' 這樣的控制碼, 而這在 UTF-8 下也沒有任何改變. 因此,
這些應用程序的 UTF-8 編碼與解碼將完全在終端模擬器里完成.</P>
<P>而那些通過數字節數來獲知字符數量的程序則需要一些小修改. 在 UTF-8 模式下, 它們必須不數入 0x80 到 0xBF 范圍內的字節,
因為這些只是跟隨字節, 它們本身并不是字符. 例如, <SAMP>ls</SAMP> 程序就必須要修改, 因為它通過數文件名中字符數來排放給用戶的目錄表格布局.
類似地, 所有的假定其輸出為定寬字體, 并因此而格式化它們的程序, 必須學會怎樣數 UTF-8 文本中的字符數. 編輯器的功能, 如刪除單個字符,
必須要作輕微的修改, 以刪除可能屬于該字符的所有字節. 受影響有編輯器 (<SAMP>vi,emacs</SAMP>, 等等)以及使用
<SAMP>ncurses</SAMP> 庫的程序.</P>
<P>Linux 核心使用軟轉換也可以工作得很好, 只需要非常微小的修改以支持 UTF-8. 大多數處理字符串的核心功能 (例如: 文件名, 環境變量, 等等)
都不受影響. 下列地方也許必須修改:
<UL>
<LI>控制臺顯示與鍵盤驅動程序 (另一個 VT100 模擬器) 必須能編碼和解碼 UTF-8, 必須要起碼支持 <B
style="COLOR: black; BACKGROUND-COLOR: #ffff66">Unicode</B> 字符集的幾個子集. 從 Linux
1.2 起這些功能已經有了.
<LI>外部文件系統驅動程序, 例如 VFAT 和 WinNT 必須轉換文件名字符編碼. UTF-8 已經加入可用的轉換選項的列表里了, 因此
<SAMP>mount</SAMP> 命令必須告訴核心驅動程序用戶進程希望看到 UTF-8 文件名. 既然 VFAT 和 WinNT 無論如何至少已經用了
<B style="COLOR: black; BACKGROUND-COLOR: #ffff66">Unicode</B>了, 那么 UTF-8
在這里就可以發揮其優勢, 以保證轉換中無信息損失.
<LI>POSIX 系統的 tty 驅動程序支持一種 "cooked" 模式, 有一些原始的行編輯功能. 為了讓字符刪除功能工作正常,
<SAMP>stty</SAMP> 必須在 tty 驅動程序里設置 UTF-8 模式, 因此它就不會把 0x80 到 0xBF 范圍內的跟隨字符也數進去了.
<A href="http://clisp.cons.org/~haible/">Bruno Haible</A> 那里已經有了一些
<SAMP>stty</SAMP> 和核心 tty 驅動 程序的 <A
href="ftp://ftp.ilog.fr/pub/Users/haible/utf8/">Linux 補丁 </A>了. </LI></UL>
<H2>C 對 <B style="COLOR: black; BACKGROUND-COLOR: #ffff66">Unicode</B> 和 UTF-8
的支持</H2>
<P>從 GNU glibc 2.1 開始, <SAMP>wchar_t</SAMP> 類型已經正式定為只存放獨立于當前 locale 的, 32位的 ISO
10646 值. glibc 2.2 開始將完全支持 ISO C 中的多字節轉換函數 (wprintf(),mbstowcs(),等等), 這些函數可以用于在
wchar_t 和包括 UTF-8 在內的任何依賴于 locale 的多字節編碼間進行轉換.</P>
<P>例如, 你可以寫</P><PRE> wprintf(L"Sch鰊e Gr
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -