Unicode字符編碼標準

Unicode

1. 編碼知識
1.1 文本和字符
在計算機程序中或者數據文件裏,文本(text)是作爲數字序列存儲的。序列中的數字是具有不同大小、取值和解釋的整數。如何解釋這些整數是由字符集(character set)、編碼(encoding)決定的。
文 本主要是由字符(character)組成。在格式文本(fancy text, or rich text)中包括顯示屬性,如顏色、斜體字、上標等,但仍然是以字符組成的純文本(plain text)爲基礎的。有時,格式文本與純文本之間的區別很複雜,依賴於具體的應用。
什麼是字符?典型地,是字母。也可以是數字、句點、連字號、標點符號和數學符號,對於中文,也可以是漢字。還包括定義行尾和段落等的控制字符(一般不可見)。
有了字符,就可以爲它們分配數字編碼。爲字符分配什麼數字值,依賴於具體情況。一個簡單的字符,如字母"a",在不同的程序或者數據文件中可能具有不同的整數值。
1.2 字符集:具有數字編碼的字符
在信息處理中,所使用的整數總有上限,依賴於存儲整數的位的數目。這也決定了可以同時區分的字符的數量。
在設計字符集時,首先要決定所需字符的數目,並確定所需字符的清單。根據字符的數目,可以設定整數值的上限,這個整數範圍稱爲編碼空間(code space),其中的一個特定整數稱爲一個碼點(code point)。
然後,爲字符清單中的每個字符指定一個整數值,也就是一個碼點。這樣就得到一個字符集,稱作編碼字符集(Coded Character Set)。
1.3 編碼單元、字節和編碼
在 計算機系統的實現中,整數以特定大小的單元表示,通常爲8位(1字節),16位,或32位。在字符編碼中,這樣的單元稱爲編碼單元(code unit)。根據編碼空間的大小和具體要求,來選擇合適的編碼單元。通常,所選擇編碼單元對應的整數範圍要大於編碼空間的整數範圍,這樣每個碼點就只需一 個編碼單元表示,並且在字符碼點與編碼單元間的轉換非常簡便,因爲字符碼點對應的整數值與相應編碼單元的整數值相同。如果編碼單元對應的整數範圍小於編碼 空間的整數範圍,就需要多個編碼單元表示一個碼點。
字節是計算機系統中最基本的表示單元,無論是存儲在內存中,還是將文本寫入文件或通過網絡發送,總是要讀寫若干字節。因此,在實際應用中,還需要將編碼單元進一步表示爲字節序列。
將字符表示爲字節序列的過程就稱爲編碼(encoding),更重要的是,還包括如何對字節序列進行解釋以取得字符。
1.4 不同的字符集
在一些常用的編碼中,每個字符只使用一個字節表示,稱單字節字符集(single-byte character set, SBCS)。這些字符集都僅限於256個字符。
在ASCII之後,目前應用最廣泛的單字節字符集是ISO-8859-1。它是ASCII的一個8位超集,並且提供西歐語言所需的大多數字符。它的一個改進的版本,ISO-8859-15,還包括新的歐元符號和更多的一些法語和芬蘭語字母。
   雙字節字符集(double-byte character set, DBCS)用於爲東亞書寫系統中所使用成千上萬個表意字符提供足夠空間。這裏的編碼仍是基於字節的,不過是兩個字節一起表示一個單一的字符。
   即使在東亞,文本中也會包含小字母表中的字母,如拉丁字母表。這些字母使用單字節表示的效率會更高。因此,提出了多字節字符集(multi-byte character set, MBDC),使用可變數目的字節來表示字符。多字節字符集通常與ASCII兼容,也就是說,在這種編碼中,拉丁字母使用與ASCII中相同的字節來表示。 一些不常用的字符可能會使用三個甚至四個字節編碼。
1.4 常見字符集
1.4.1 ASCII: The American Standard Code form Information Interchange
   ASCII是一個使用7位單元的字符集,及針對7位字節的簡單編碼方式。儘管侷限於很少的一些字符,ASCII是最重要的一種字符集,因爲它是目前大多數字符集的基礎。
   ASCII只提供了128個數字值(也可稱作碼點,code point),其中33個被保留用作特殊功能。只有95個碼點用作"真正的"文本字符。這些圖形字符大多時大寫和小寫拉丁字母,數字和標點符號,外加一些特殊的括號、下劃線和重音符號。
1.4.2 EBCDIC: The Extended Binary-Coded Decimal Interchange Code
EBCDIC是由IBM設計的編碼格式,使用8位字節,被一些字符集用於大型機。EBCDIC在與ASCII相近的時期開發的,具有一些相似的特性。
1.4.3 Unicode
Unicode標準定義了一個字符集和幾種編碼。
Unicode最有吸引力的特點是它涵蓋了幾乎世界上的所有字符,可以只通過一個唯一的數字(Unicode碼點)來訪問和操作字符。
2. Unicode介紹
2.1 爲什麼使用Unicode?
在創造Unicode之前,有數百種編碼系統。但是,沒有任何一個編碼可以包含足夠的字符。例如,僅歐州共同體就需要好幾種不同的編碼來包括所有的語言。即使是單一的一種語言,如英語,也沒有哪一個編碼可以適用於所有的字母,標點符號,和常用的技術符號。
這些編碼系統也會互相沖突。也就是說,兩種編碼可能使用相同的數字代表兩個不同的字符,或使用不同的數字代表相同的字符。任何一臺特定的計算機(特別是服務器)都需要支持許多不同的編碼,但是,不論什麼時候數據通過不同的編碼或平臺之間,那些數據總會有損壞的危險。
而Unicode正在改變所有這一切!
在Unicode標準中,提供了1,114,112個碼點,不僅可以包含當今世界使用的所有語言文字和其他符號,也足夠容納絕大多數具有歷史意義的古文字和符號。並且,Unicode給每個字符提供了一個唯一的數字,不論是什麼平臺,不論是什麼程序,不論什麼語言。
Unicode 標準已經被工業界的領導們所採用,例如:Apple, HP, IBM, JustSystem, Microsoft, Oracle, SAP, Sun, Sybase, Unisys等等。最新的標準都需要Unicode,例如XML, Java, ECMAScript , LDAP, CORBA 3.0, WML等等,並且,Unicode是實現ISO/IEC 10646的正規方式。許多操作系統,所有最新的瀏覽器和許多其他產品都支持它。Unicode標準的出現和支持它工具的存在,是近來全球軟件技術最重要 的發展趨勢。
2.2 Unicode與國際化
直到最近,國際化的常用方法是,假定任何給定的可執行程序同時只和一種語言工作。如果在英文環境下安裝,它就只處理英文文本;如果在中文環境下安裝,就只處理中文文本。
在 這種模型下,針對不同的書寫系統和語言,使用的字符集和字符編碼不同。在Windows和大型機環境下,術語"代碼頁"(Code Page)用於描述如何將二進制值映射到人類可讀得字符(字形)。一個運行的程序處在單一的代碼頁,該代碼頁確定二進制值如和與字形關聯。
簡便的國際化是Unicode的另一項優勢。在內部使用Unicode的應用程序,能夠同時存儲和處理世界上所有的字符,這消除了傳統的國際化方法所面臨的一些困難。
當然,成功的國際化不僅僅是在應用程序中採用Unicode,還需要謹慎的屏幕布局設計(不同的語言具有不同的書寫習慣)、翻譯和文化理解。
2.3 設計原則
Unicode的設計反映了十大基本原則,但這些原則並不是可以同時滿足。整個設計是在保證簡便高效和保持與已有編碼標準兼容之間的平衡。
(1)廣泛性(Universality)
Unicode標準對一個單一的大字符集進行編碼,包括滿足世界範圍需求的所有字符。
(2)高效(Efficiency)
在Unicode的字符編碼模型中沒有換碼符(escape character),每個字符編碼與其它字符編碼具有相同的狀態。使高效率的實現成爲可能。
所有Unicode編碼方式都是自同步的,並且相互不重疊。使在字符流中隨機訪問和查找操作高效。
同一書寫字母體系中的字符被放置在一起,不僅方便字符的查找,並且使實現更緊湊壓縮方法更高效。
(3)針對字符編碼,而不是字形(Character, Not Glyph)
字符是書寫語言中具有語義的最小組件的抽象表示。字符是以駐留在內存中的碼點表示。
字形是字符被顯示時具有的形狀。與字符相比,字形出現在屏幕或紙張上作爲一個或多個字符的特定表示。字形的集合構成一種字體。
字符和字形間存在多種關係:一個字形可以對應一個字符;一個字形也可以對應幾個字符;多個字形也可能出自一個字符。
(4)語義(Semantic)
在Unicode中,字符都有明確定義的語義。字符屬性表可用於解析、排序等需要有關碼點語義知識的算法中。Unicode中定義的屬性包括數字、間隔、組合和方向屬性。
(5)純文本(Plain Text)
純文本或無格式文本,僅僅是字符編碼的序列。純Unicode文本就是Unicode編碼的序列。而格式文本(styled text, or rich text)是由純文本添加一些附加信息(如語言標識、字體大小、顏色等)組成的文本表示。
Unicode標準針對的是純文本。
(6)邏輯順序(Logical Order)
Unicode文本在內存表示中以邏輯順序存儲,大致對應於藉助鍵盤輸入文本的順序。在一些情況下,當顯示或打印文本時,字符順序與邏輯順序不同。
(7)統一(Unification)
Unicode標準爲避免對字符重複編碼,對不同語言書寫方式中的字符進行統一,相同的字符分配唯一的一個編碼。普通字母、標點符號、標記,和變音符都只分配一個編碼,而不管語言;同樣的還有中日韓使用的表意字符。
(8)動態組合(Dynamic Composition)
Unicode標準允許加重音符好的形式和Hangul音節的動態組合。
(9)等價序列(Equivalent Sequences)
一些文本元素即可以使用靜態的預先組合好的形式,也可使用動態組合的形式。Unicode字符的不同表示序列被認爲是等價的。
如果兩個或多個序列被認爲是等價的,Unicode標準不規定哪一種特定的序列是正確的,而認爲每一個序列只不過與其它序列等價。
如 果需要一種單一的單一的表示方式,可以使用一種規範化的Unicode文本形式來減少不想要區別。Unicode標準定義了四種規範化形式: Normalization Form D (NFD),Normalization Form KD (NFKD),Normalization Form C (NFC),和Normalization Form KC (NFKC)。大約來說,NFD和NFKD將可能的字符進行分解,而NFC和NFKC將可能的字符進行組合。
(10)可轉換性(Convertibility)
在Unicode 標準和其他字符集標準之間可以實現準確的轉換。一般說,在其他標準中的一個碼點對應於Unicode標準中一個單一的碼點。然而,有時在其他標準中的一個 碼點對應於Unicode標準中一個碼點的序列。在Unicode文本和其他字符編碼文本間的轉換一般是通過明確的表映射過程完成的。
2.4 Unicode的碼點、編碼格式、編碼方案
2.4.1 Unicode編碼空間和碼點
在Unicode標準中,編碼空間的整數範圍是從0到10FFFF(16進制),共1,114,112個可用的碼點。
爲了與已有的編碼標準兼容,一些抽象字符可能會與多個分別編碼的字符關聯。而在其他一些情況下,一個抽象字符可能會用兩個(或更多)編碼字符序列來表示,如帶重音符的字母。
2.4.2 Unicode編碼格式
在Unicode字符編碼模型中,編碼格式(encoding form)指定如何將每個碼點表示爲一個或多個編碼單元序列。Unicode標準提供了三種不同的編碼格式,使用8位、16位和32位編碼單元,分別爲UTF-8、UTF-16、UTF-32。
(1)UTF-32
UTF-32是一種最簡單的Unicode編碼格式。每個Unicode碼點被直接表示爲一個32位的編碼單元。UTF-32是一種固定寬度的字符編碼格式。
每個UTF-32編碼單元的值與Unicode碼點的值完全相同。
(2)UTF-16
在UTF-16中,在範圍U+0000到U+FFFF間的碼點使用一個單一的16位編碼單元表示;而,在範圍U+10000到U+10FFFF間的碼點則使用一對16位編碼單元表示,稱作代理對(surrogate pair)。
UTF -16優化了基本多語言平面(Basic Multilingual Plane)中字符的表示,即位於U+0000到U+FFFF範圍內的字符。該範圍包含了目前世界上所使用的書寫系統中的絕大多數字符,每個字符只需要一 個16位的編碼單元。對於基本多語言平面,UTF-16可作爲固定寬度的編碼格式來有效使用。
但對於增補字符,UTF-16需要兩個16位的編碼單元,意味着正式的UTF-16是一個變寬的編碼格式。
UTF-16是早期Unicode遺留下的歷史產物,原本被設計成具有固定寬度的16位編碼格式。爲支持超過U+FFFF的增補字符,設立了代理機制。
(3)UTF-8
爲滿足基於ASCII,面向字節的系統的需要,Unicode標準中定義了第三種編碼格式UTF-8。它是一種使用8位編碼單元的變寬的編碼格式。
在UTF-8的編碼單元種,一些高位用於指示當前字節在編碼單元序列中的那一部分。8位編碼單元的取值的一部分範圍保留給UTF-8的編碼單元序列的首字節;另一部分完全奮力的範圍保留給序列中的後續字節,以保證UTF-8不重疊。
UTF -8編碼格式對所有ASCII碼點具有透明性。在U+0000到U+007F範圍內的Unicode碼點,被轉換爲UTF-8中單一的字節0x00到 0x7F,與ASCII碼沒有區別。並且,從0x00到0x7F不會出現在其他Unicode碼點的UTF-8表示中的任一字節中,保證了不存在歧義。
Unicode中超出ASCII範圍的其他一些非表意字母,每個都在UTF-8種使用量各字節表示;位於U+0800到U+FFFF範圍內的非代理碼點使用三字節表示;超出U+FFFF的增補碼點則需要四字節表示。
UTF-8是Internet中HTML和類似協議偏好的編碼格式。
UTF-8同其他的多字節編碼方式相比具有以下特點:
a) UTF-8的編碼單元序列的第一個字節指明瞭後面所跟的字節的數目。對前向解析非常有效。
b) 從UTF-8字節流的任意位置開始可以有效的找到一個字符的其實位置。
c) UTF-8中不存在字節取值的重疊。
2.4.3 Unicode編碼方案
在Unicode標準中,用於Unicode數據字節串行化的各種不同類型的規範被稱爲Unicode編碼方案(encoding scheme)。
在計算機系統中,大數值類型(如整型)使用多個字節表示,不同體系結構採用的字節排列順序不同。其中,部分採用由高字節到低字節的排列順序,稱爲big-endian;其他則採用由低字節到高字節的排列順序,稱little-endian。
對於UTF-16和UTF-32,字節串行化規範必須考慮當前表示數據的系統採用的是big-endian還是little-endian結構。
一個字符編碼方案包括指定的字符編碼格式,以及如何將編碼單元串行化爲字節的規範。在Unicode標準中,還規定了初始的字節順序標誌(byte order mark, BOM)的使用,用於顯示區分big-endian和little-endian數據。
對於UTF-8,在序列中只包括UTF-8的編碼單元(1字節),因此,UTF-8中的數據表示不存在字節順序的問題。但對於16位和32位的編碼方案,字節串行化過程必須將編碼單元分解爲兩個或四個字節,並且必須清楚的定義這些字節的順序。
因此,Unicode標準中定義的三種編碼格式,導致總共七種Unicode編碼方案,分別爲:UTF-8、UTF-16、UTF-16BE、UTF-16LE、UTF-32、UTF-32BE、UTF-32LE。
必須明確,字符編碼格式(character encoding form)指在內存或API中的整數數據單元,與字節順序不相關;字符編碼方案(character encoding scheme)指字節串行化的數據,如I/O流或者文件,必須制定字節順序。
2.4.4 Unicode編碼空間分配
根據在語言學上和功能上的類別,Unicode標準中的編碼字符被分成組。
Unicode 編碼空間的範圍爲0到10FFFF,可以被劃分爲字符平面(planes of characters),每個平面包含64K各碼點。因此,最底層的平面爲基本多語言平面(Basic Multilingual Plane),包括範圍從0000到FFFF;下一個平面爲增補多語言平面(Supplementary Multilingual Plane),也被稱爲第一平面(Plane 1),包括範圍10000到1FFFF;以及,第二平面(Plane 2),增補表意字符平面(Supplementary Ideographic Plane),包括範圍20000到2FFFF;等等。基本多語言平面有時也被稱爲Plane 0。
基本多語言平面(BMP, or Plane 0)包含目前世界上使用的所有書寫系統中的全部常用字符,以及一些歷史上的不常用字符。
增補多語言平面(SMP, or Plane 1)用於一些較少使用的歷史上的書寫系統,針對特殊目的創建的書寫系統,和特殊的標記系統,它們要麼無法放入基本多語言平面中,要麼特別不常用。
增補表意字符平面(SIP, or Plane 2)用於無法放入基本語言平面衆所分配區域中/日/韓字符(CJK character)。儘管在SIP中包含少量的常用CJK字符(例如,用於粵語),其中絕大多數字符是僅具有歷史意義的不常用字符。
增補專用平面(Supplementary Special-purpose Plane, SSP, or Plane 14)用於無法放入基本多語言平面衆所分配區域的格式控制字符。
3. 一致性
符合Unicode一致性要求的實現必須滿足本部分定義的標準,以便與其他規範的實現進行交互。
3.1 一致性要求
3.1.1 未分配的碼點(Unassigned Code Points)
C4 處理過程不應該把高代理碼點(high-surrogate code point)或者低代理碼點(low-surrogate code point)解釋爲抽象字符。
C5 處理過程不應該把非字符碼點解釋爲抽象字符。
C6 處理過程不應該將未分配的碼點解釋爲抽象字符。
3.1.2解釋(Interpretation)
C7 如果處理過程要解釋編碼字符的表示,就必須根據標準中確立的字符語義進行解釋。
C8 不要求處理過程對任何特定的編碼字符都作解釋。
 允許處理過程只解釋Unicode字符中的一個子集;不需要解釋所有Unicode字符。
 標準中不涉及任何指定字符子集的方法。
 標準中不涉及自定義區中碼點的語義。
C9 處理過程不應認爲對兩個具有規範等價性字符序列(canonical-equivalent character sequence)的解釋會不同。
 該條款包含兩層意義:(一)處理過程不應該對兩個不同但又具有規範等價性的字符序列由不同的解釋;(二)任何處理過程不應假設其他處理過程會對兩個不同但具有規範等價性的字符序列進行不同的解釋。
3.1.3 修改(Modification)
C10 如果一個處理過程聲稱不會修改對一個正確的編碼字符表示的解釋,則它不能對編碼字符的表示進行任何修改,除非是用具有規範等價性的字符序列進行替換,或者是刪除非字符的碼點。
 用具有規範等價性的字符序列替換原有字符序列不會修改對文本的解釋。
 替換或者刪除處理過程不能會不進行解釋的字符序列,不修改對文本的解釋。
 當在不同計算機體系結構間轉換字符序列時,對字符序列位或者字節順序的改變,不修改對文本的解釋。
 將一個正確的編碼字符的表示從一種Unicode字符編碼格式轉換爲另一種編碼格式時,不修改對文本的解釋。
 將編碼單元序列的字節串行化從一種Unicode字符編碼方案轉換爲另一種編碼方案時,不修改對文本的解釋。
 如果在處理過程中意外遇到一個沒有明確內部用途的非字符,在實現中可以發出錯誤,或者刪除或忽略該非字符。如果沒有采取這些選擇,這個非字符應該被作爲一個爲分配的碼點。
3.1.4 字符編碼格式(Character Encoding Forms)
C11 當處理過程對一個聲稱以某種Unicode字符編碼格式存在的編碼單元序列進行解釋時,必須按照相應的碼點序列進行解釋。
C12 當處理過程以某種Unicode字符編碼格式生成編碼單元序列時,不應生成形式錯誤(ill-formed)的編碼單元序列。
C12a 當處理過程對一個聲稱以某種Unicode字符編碼格式存在的編碼單元序列進行解釋時,應該將形式錯誤的編碼單元序列看作錯誤條件,而不能將序列解釋爲字符。
3.1.5 字符編碼方案(Character Encoding Schemes)
C12b 當處理過程對一個具有某種Unicode字符編碼方案的字節序列進行處理時,應該根據字節順序和標準中針對字符編碼方案設立的字節順序標記(byte order mark)使用規範,進行解釋。
3.1.6 雙向文本(Bidirectional Text)
C13 用於顯示包含從右到左的字符文本的處理過程,當沒有高層協議時,必須以對文本應用雙向算法後同樣的順序顯示所有具有可見表示的字符(不包括格式字符)。
3.1.7 正規化形式(Normalization Forms)
C14 以某種正規化形式生成Unicode文本的處理過程,必須與Unicode Standard Annex #15 "Unicode Normalization Forms"中定義的規範相符合。
C15 測試Unicode文本是否具有某種正規化形式的處理過程,必須與必須與Unicode Standard Annex #15中定義的規範相符合。
C16 將文本轉換爲某種正規化形式的處理過程必須生成Unicode Standard Annex #15中規定的結果。
3.1.8 標準的引用(Normative References)
C17 對標準、屬性別名、屬性值別名或者Unicode算法的標準引用,必須依照Unicode標準種指定的格式。
C18 高層協議不能對臨時屬性進行標準引用。
3.1.9 Unicode算法(Unicode Algorithms)
C19 如果處理過程聲稱實現某個Unicode算法,則必須符合標準中定義的算法規範,除非被高層協議改變。
3.2 術語定義
以下是對一致性條款中所使用術語的準確定義。
3.2.1 字符的身份和語義(Character Identity and Semantics)
D1 標準的行爲(normative behavior):Unicode標準中的標準行爲包括以下列表,以及在一致性條款種指定的其他行爲。
1. 字符組合;
2. 規範化的分解;
3. 兼容的分解;
4. 規範的排序行爲;
5. 雙向行爲;
6. 聯合jamo行爲(conjoining jamo behavior);
7. 變化選擇;
8. 正規化。
D2a 字符身份(character identity):一個字符的身份是由它的字符名稱、表示的字形確定的。
D2b 字符語義(character semantics):一個字符的語義是由它的身份、標準的屬性和行爲決定的。
3.2.2 字符與編碼(Characters and Encoding)
D3 抽象字符(abstract character):信息的單元,用於文本數據的組織、控制或表示。
 抽象字符沒有具體的形狀,不應與字形混淆。
 Unicode標準中沒有直接編碼的抽象字符經常可以使用組合字符序列表示。
D4 抽象字符序列:抽象字符的有序序列。
D4a Unicode編碼空間(Unicode codespace):從0到10FFFF的整數空間(十六進制)。
D4b 碼點(code point):Unicode編碼空間中的任何一個整數值。
 一個碼點也稱爲一個編碼位置。
D5 編碼字符(encoded character):在一個抽象字符和一個碼點間的關聯。
 在Unicode中,爲了與其它標準兼容,一個單個的抽象字符可能與多個碼點對應。
 一個單個的抽象字符也可能使用一個碼點序列表示。
D6 編碼字符表示(coded character representation):一個碼點序列。通常,是由編碼字符的序列組成,但也可能包含非字符或保留的碼點。
 編碼字符表示也稱爲編碼字符序列(coded character sequence)。
 在內部,處理過程可能會在編碼字符表示中使用非字符碼點。但是,這些非字符碼點可能不會被解釋成抽象字符;並且,如果這些非字符碼點被具有一致性的處理過程刪除,不構成對編碼字符表示解釋的修改。
D7a 不贊成使用的字符(deprecated character):強烈不鼓勵使用的編碼字符。
 在標準中保留不贊成使用的字符,以便使以前相容的數據仍然與今後的Unicode標準保持一致性。
D7b 非字符(noncharacter):被永久保留做內部使用的碼點,不應用於交換。非字符包括值U+nFFFE和U+nFFFF(n表示十六進制整數從0到10),以及值從U+FDD0到U+FDEF。
D7c 保留的碼點(reserved code point):Unicode標準中保留的,用於今後分配的碼點。也稱爲位分配碼點(unassigned code point)。
 代理碼點和非字符碼點是已分配的碼點,但不是分配給字符。
D8 高層協議(higher-level protocol):任何超出Unicode標準範圍,對Unicode字符進行解釋協議。
D8a Unicode算法(Unicode Algorithm):對處理過程的邏輯描述,用於獲得涉及Unicode字符的指定結果。
3.2.3 屬性(Properties)
(1)標準的和指示性屬性(Normative and Informative Properties)
Unicode字符屬性可以分爲標準的和指示性的。
D9 標準屬性(normative property):Unicode字符屬性,它的取值必須爲與標準相一致。
D9a 指示性屬性(Informative property):Unicode字符屬性,它的取值僅僅是爲了提供更多信息。
D9b 臨時的屬性(provisional property):Unicode字符屬性,它的取值未被批准、試驗性的,也可能是不完全的。
(2)簡單的和衍生出的屬性(Simple and Derived Properties)
D9c 簡單屬性(simple property):Unicode字符屬性,它的取值在UCD,the Unicode Character Database(或標準中的其他地方)直接指定,並且它的取值無法從其他簡單屬性中衍生出來。
D9d 衍生屬性(derived property):Unicode字符屬性,它的取值可通過算法從一些簡單屬性的組合中衍生出來。
(3)屬性別名(Property Aliases)
D10 屬性別名(property alias):特定Unicode字符屬性的一個唯一標示名。
 用於屬性別名的標示名中僅包含ASCII中的字母、數字和下劃線。
 爲每個屬性別名分別定義了長、短兩種形式的名稱。短的形式一般只有兩個或三個字符長,便於在標記語言中用於標記屬性。
D10a 屬性值別名(property value alias):爲Unicode字符屬性的特定取值定義的唯一標示名。
 用於屬性值別名的標示名中僅包含ASCII中的字母、數字和下劃線,或者是特殊的值"n/a"。
 爲每個屬性值別名分別定義了長、短兩種形式的名稱。
 屬性值別名僅在相關聯的特定屬性環境中唯一。
(4)卻省屬性值(Default Property Value)
D11 卻省屬性值(default property value):針對一個給定的Unicode屬性,用於指派給未分配的碼點或沒有明確指定其他屬性值的屬性值。
(5)私用(Private Use)
D12 私用碼點(private-use code point):在範圍U+E000到U+F8FF、U+F0000到U+FFFFD和U+100000到U+10FFFD內的碼點。
 私用碼點被認爲已分配給字符,但標準中沒有指定對私用碼點相關聯的抽象字符的解釋。
 私用碼點可能會被賦予卻省的屬性值,但這些卻省值可以被對私用碼點進行解釋的高層協議替換。
3.2.4 組合(Combination)
D13 基字符(base character):在書寫上,不與前面的字符進行組合的字符,它既不是控制字符也不是格式字符。
D14 組合字符(combining character):在書寫上,與前面的基字符進行組合的字符。稱組合字符應用於基字符。
 組合字符不單獨使用。它們包括重音符、變音符、希伯萊文中的點、阿拉伯文元音符號等。
 儘管組合字符用來與基字符組合顯示的,但可能出現兩種情況(1)在組合字符前沒有基字符;(2)處理過程無法執行組合操作。在這兩種情況下,處理過程可能會不進行書寫上的合併而顯示組合字符。
 在編碼表中,組合字符的表示使用虛線圓圈描繪。當與前面的基字符組合顯示時,基字符要出現在虛線圓圈的位置上。
 組合字符一般具有它們的基字符的屬性,同時保留它們的組合屬性。
 控制字符和格式字符,如tab和right-left mark不是基字符。
D15 非間距標記(nonspacing mark):在顯示時,位置取決於基字符的組合字符。這些字符一般在可視基線上不佔用空間。
 這些字符可能會很大,影響它們的基字符相對於前後基字符的放置。
D16 間距標記(spacing mark):不是非間距標記的組合字符。
 一般來說,間距標記的行爲與基字符沒有太大區別。
D17 組合字符序列(combining character sequence):一個字符序列,由一個基字符後跟了一個或多個組合字符組成,或者是一個或多個組合字符的組成的序列。
D17a 不良的組合字符序列(defective combining character sequence):一個不是以基字符開始的組合字符序列。
 當組合字符序列出現在串的開始位置,或者跟在控制字符或格式字符後出現時,產生不良的組合字符序列。
3.2.5 分解(Decomposition)
D18 可分解字符(decomposable character):根據分解映像表,與一個或多個字符組成的序列等價的字符。也被稱作預組合字符(precomposed character)或複合字符(composite character)。
D19 分解(decomposition):與一個可分解字符等價的一個或多個字符組成的序列。一個字符序列的完全分解,是對序列中每個字符進行分解直到沒有字符可以進一步分解。
(1)兼容的分解(Compatibility Decomposition)
D20 兼容的分解(compatibility decomposition):遞歸應用Character Names List中的兼容映像表和規範映像表,以及Conjoining Jamo Behavior中的定義,對字符進行分解,直到沒有任何字符可以進一步分解,並根據Canonical Ordering Behavior中的定義對非間距標記進行重新排序。
D21 兼容的可分解字符(compatibility decomposable character):兼容分解的結果與規範分解結果不相同的字符。
(2)規範的分解(Canonical Decomposition)
D23 規範的分解(canonical decomposition):遞歸應用Character Names List中的規範映像表,以及Conjoining Jamo Behavior中的定義,對字符進行分解,直到沒有任何字符可以進一步分解,並根據Canonical Ordering Behavior中的定義對非間距標記進行重新排序。
D21 規範的可分解字符(compatibility decomposable character):與規範分解結果不相同的字符。
D24 規範等價性(canonical equivalent):如果兩個字符序列的完全規範分解結果相同,稱它們具有規範的等價性。
3.2.6 代理(Surrogates)
D25 高代理碼點(high-surrogate code point):位於範圍U+D800到U+DBFF內的Unicode碼點。
D25a 高代理編碼單元(high-surrogate code unit):在範圍D800到DBFF內的16位編碼單元,作爲UTF-16中代理對的起始編碼單元。
D26 低代理碼點(low-surrogate code point):位於範圍U+DC00到U+DFFF內的Unicode碼點。
D26a 低代理編碼單元(low-surrogate code unit):在範圍DC00到DFFF內的16位編碼單元,作爲UTF-16中代理對的結尾編碼單元。
D27 代理對(surrogate pair):由兩個16位編碼單元組成的序列來表示單個的抽象字符,其中,代理對的第一部分爲高代理編碼單元,第二部分爲低代理編碼單元。
 代理對僅用於UTF-16。
 孤立的代理編碼單元自身沒有解釋。
3.2.7 Unicode編碼格式(Unicode Encoding Forms)
D28 Unicode標量值(Unicode scalar value):除了高代理和低代理碼點外的其他所有Unicode碼點。
D28a 編碼單元(code unit):爲了處理和交換,表示編碼文本單元的最小的位組合。
 編碼單元是計算機存儲中的特定單元。Unicode標準在UTF-8中使用8位編碼單元,在UTF-16中使用16位編碼單元,在UTF-32中使用32位編碼單元。
 在Unicode標準中,一些編碼單元的特定值不能單獨用於表示編碼字符。該限制條件應用於UTF-16中孤立的代理碼點,以及UTF-8中的字節80-FF。
D28b 編碼單元序列(code unit sequence):一個或多個編碼單元的有序序列。
 當編碼單元是8位時,編碼單元序列也可被稱作字節序列。
 一個編碼單元序列可能只有一個單個的編碼單元。
 在程序設計語言中,字符串類型的值基本由編碼單元序列組成。
 依賴字符編碼標準的結構,可能要使用編碼單元序列(包含多個編碼單元)來表示一個單個的編碼字符。
D29 Unicode編碼格式將每個Unicode標量值分配給一個唯一的編碼單元序列。
 由於歷史原因,Unicode編碼格式也被稱作Unicode(or UCS) transformation formats(UTF)。
 在Unicode標量值集合與針對Unicode編碼格式的編碼序列集合間的映射是一對一的。
 對給定的編碼格式,存在編碼單元序列沒有相關聯的Unicode標量值。
D29a Unicode串(Unicode string):由Unicode編碼格式中編碼單元組成的編碼單元序列。
D29b 8位Unicode串(Unicode 8-bit string):只包含UTF-8編碼單元的Unicode串。
D29c 16位Unicode串(Unicode 16-bit string):只包含UTF-16編碼單元的Unicode串。
D29d 32位Unicode串(Unicode 32-bit string):只包含UTF-32編碼單元的Unicode串。
D30 形式不良的(ill-formed):如果具有Unicode編碼格式的Unicode編碼單元序列沒有遵照Unicode編碼格式規範,就稱爲形式不良的。
 如果編碼單元序列對應的碼點位與Unicode標量範圍之外,就是形式不良的。
 UTF-8對起始字節和後續字節的字節範圍有嚴格的約束。違反這些約束,將使生成的編碼單元序列無法映射到Unicode標量值上,產生一個形式不良的編碼單元序列。
D30a 形式良好的(well-formed):遵照Unicode編碼格式規範的Unicode編碼單元序列,就成爲形式良好的。
D30b 形式良好的UTF-8編碼單元序列(well-formed UTF-8 code unit sequence)
D30c 形式良好的UTF-16編碼單元序列(well-formed UTF-16 code unit sequence)
D30d 形式良好的UTF-32編碼單元序列(well-formed UTF-32 code unit sequence)
D30e 具有Unicode編碼格式(in a Unicode encoding form):如果一個Unicode串是由某個特定的Unicode編碼格式的形式良好的編碼單元序列組成,稱該Unicode字符串具有Unicode編碼格式。
UTF-32
D31 UTF-32編碼格式(UTF-32 encoding form):一種Unicode編碼格式,爲每個Unicode標量值分配一個單一的無符號的32位編碼單元,編碼單元的數字值與Unicode標量值相同。
 因爲代理碼點沒有包括在Unicode標量值集合中,所以位與範圍0000D800到0000DFFF間的UTF-32編碼單元使形式不良的。
 任何大於0010FFFF的UTF-32編碼單元是形式不良的。
UTF-16
D35 UTF-16編碼格式(UTF-16 encoding form):一種Unicode編碼格式,爲處在範圍U_0000到U+D7FF和U+E000到U+FFFF內的每個Unicode標量值分配一個單一 的無符號的16位編碼單元,編碼單元的數字值與Unicode標量值相同;位處在範圍U+10000到U+10FFFF內的每個Unicode標量值分配 一個代理對。
 因爲代理碼點不是Unicode標量值,位於範圍D800到DFFF間單獨的UTF-16編碼單元是形式不良的。
UTF-16 Bit Distribution
Scalar Value UTF-16
xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
000uuuuuxxxxxxxxxxxxxxxx 110110wwwwxxxxxx110111xxxxxxxxxx
wwww=uuuuu-1
UTF-8
D36 UTF-8編碼格式(UTF-8 encoding form):一種Unicode編碼格式,位每個Unicode標量值分配一個由一到四個無符號字節組成的序列。
UTF-8 Bit Distribution
Scalar Value 1st Byte 2nd Byte 3rd Byte 4th Byte
00000000 0xxxxxxx 0xxxxxxx
00000yyy yyxxxxxx 110yyyyy 10xxxxxx
zzzzyyyy yyxxxxxx 1110zzzz 10yyyyyy 10xxxxxx
000uuuuu zzzzyyyy yyxxxxxx 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
編碼格式轉換(Encoding Form Conversion)
D37 編碼格式轉換:在一種Unicode編碼格式的編碼單元序列與另一種Unicode編碼格式的編碼單元序列間,直接定義的轉換。
  * 在Unicode標準實現中,一個典型的API在邏輯上,將輸入的編碼單元序列轉化爲Unicode標量值(碼點),然後將標量值轉化爲輸出的編碼單元序列。然而,可以直接在不同編碼格式間進行轉換,以獲取更高的效率。
  * 具有一致性的編碼格式轉換過程應將任何形式不良的編碼單元序列作爲一個錯誤條件。
3.2.8 Unicode編碼方案(Unicode Encoding Schemes)
D38 Unicode編碼方案:針對Unicode編碼格式的一種指定的字節串行換,也可包括處理字節順序標記(byte order mark, BOM)的規範。
D39 UTF-8編碼方案(UTF-8 encoding scheme):對UTF-8編碼單元序列進行串行化的Unicode編碼方案,字節序列與編碼單元序列本身完全一致。
D40 UTF-16BE編碼方案(UTF-16BE encoding scheme):將UTF-16編碼單元序列串行化爲big-endian格式字節序列的Unicode編碼方案。
D41 UTF-16LE編碼方案(UTF-16LE encoding scheme):將UTF-16編碼單元序列串行化爲little-endian格式字節序列的Unicode編碼方案。
D42 UTF-16編碼方案(UTF-16 encoding scheme):將UTF-16編碼單元序列串行化爲big-endian或者little-endian格式字節序列的Unicode編碼方案。
 在UTF-16編碼方案中,與U+FEFF對應的初始字節序列,被解釋爲字節順序標記(BOM),用於區分兩種字節順序。初始字節順序<FE FF>表明是big-endian順序,<FF FE>表明是little-endian順序。BOM不是文本內容的一部分。
 UTF-16編碼方案可能以BOM開始,也可能沒有。然而,如果沒有BOM,也沒有高層協議指示,UTF-16編碼方案的字節順序爲big-endian。
D43 UTF-32BE編碼方案(UTF-32BE encoding scheme):將UTF-32編碼單元序列串行化爲big-endian格式字節序列的Unicode編碼方案。
D44 UTF-32LE編碼方案(UTF-16LE encoding scheme):將UTF-32編碼單元序列串行化爲little-endian格式字節序列的Unicode編碼方案。
D45 UTF-32編碼方案(UTF-32 encoding scheme):將UTF-32編碼單元序列串行化爲big-endian或者little-endian格式字節序列的Unicode編碼方案。
 在UTF-32編碼方案中,與U+FEFF對應的初始字節序列,被解釋爲字節順序標記(BOM),用於區分兩種字節順序。初始字節順序<00 00 FE FF>表明是big-endian順序,<FF FE 00 00>表明是little-endian順序。BOM不是文本內容的一部分。
 UTF-32編碼方案可能以BOM開始,也可能沒有。然而,如果沒有BOM,也沒有高層協議指示,UTF-16編碼方案的字節順序爲big-endian。
3.2.9規範排序行爲(Canonical Ordering Behavior)
用於對組合字符序列提供無歧義的解釋,以便能按照可預知的方式創建和交換包含組合字符的序列。正規化是規範排序行爲的另一個重要應用。
在Unicode標準中,組合字符序列中字符的順序按照以下原則解釋:
 所有組合字符必須跟在所應用的基字符後面。
 封閉的標記(enclosing mark)將包圍基字符以及標記之前的所有組合字符。也包圍它之前的其他封閉標記。
 double diacritic的結合程度比其他非間距標記(nonspacing mark)要鬆。當顯示時,double diacritic的位置在其他變音符之上,不包括封閉的變音符。
 具有相同組合類別(combining class)的組合標記在書寫上的位置一般是由所修飾的基字符向外排列。一些特定的非間距標記將改變卻省的排列行爲,與相鄰的非間距標記並行排列。當並行排列時,編碼的順序與書寫中佔支配的順序有關。
 如果組合字符的組合類別不同,將不會有顯示形式或語義上的差別。
(1)組合類別(Combining Class)
D46 組合類別:分配給每個Unicode組合字符的數字值,用於確定與那些組合字符在排字上相互作用。
 如果組合字符間在排字上相互作用,則具有相同的組合類別;否則,具有不同類別。
 封閉字符和間距組合字符的組合類別與它們的基字符相同。
 組合類別具有的特定數字沒有特別的重要性,只是用來比較是否相等,區分不同的組合類別。
(2)規範排序(Canonical Ordering)
對一個被分解的字符序列的規範排序,是根據組合類別對每個組合字符序列進行排序來完成的。字符序列的規範排序不反映任何語言正確性或偏好。
對被分解的字符序列D進行規範排序的算法爲:
R1 對D中的任意字符x,定義p(x)爲字符x的組合類別。
R2 如果在D中存在想的字符對(A,B),並且p(B)不爲零,p(A)>p(B),則交換兩個字符。
R3 重複執行R2,直到在D中沒有發生任何交換。
(3)Conjoining Jamo Behavior
在Unicode標準中包含了一套預組合的Hangual音節,以及一套用於表示古老的韓文音節和現代韓文音節的jamo。
4. 實現指南
4.1 編碼轉換(Transcoding to Other Standards)
一般,在Unicode標準和其他編碼標準間的映射需要通過表(table)來完成,而不是算法轉換。使用表查找常常具有比簡單算法轉換更高的效率。
(1)多級表(Multistage Tables)
轉 換表需要空間。即使是很小的字符集也經常會映射到Unicode標準中幾個不同的區塊中,因此,至少在一個轉換方向上(從Unicode標準到其他編碼標 準或相反),可能會包含多至64K個項(針對BMP)或1,088K個項(針對全部編碼空間)。有多個方法用於減少映射表的內存空間需求,這些方法不僅可 用於轉換表,也可用於其他實現Unicode標準的表結構,包括字符屬性數據、case映射等等。
(2)Flat Tables
如果磁盤空間不是問題,虛擬內存體系可以爲flat table安排可接受大小的工作集,因爲各字符的使用頻率有很大不同,即使是小字符集也包含一些不常使用的字符。並且,需要轉換爲給定字符集的數據中的字符一般不會來自Unicode標準中的所有區塊。
(3)Ranges
提 供一個精心創建的嵌套範圍判斷對錶進行優化,可能比較吸引人。但由於分支損失,這種方法會對現代的高度流水線式的處理器體系造成不必要的性能耗費。一種快 速的解決方案是採用優化的兩級表,可以在編碼中不包含任何測試或分支指令。儘管哈希表的速度不如多級表,但也可用於空間優化。
(4)兩級表(Two-Stage Tables)
兩 級表示常用的一種減少表的大小的機制。兩級表使用一個指針和卻省值的數組。如果指針爲空NULL,查找返回卻省值。否則,指針指向用於第二級查找的數值 塊。對於BMP字符,按照高字節和低字節值來組織這樣的兩級表非常有效,第一級是由256個指針組成數組,每個第二集區塊中包含256個值。對於增補字 符,應採取不同的方法構造指針和二級數組,以便充分考慮增補字符在剩餘編碼空間中稀疏的散佈。
(5)優化的兩級表(Optimized Two-Stage Table)
當 任何區塊相同時,對應的指針只需其中一個區塊。對編碼轉換表而言,這種情況一般出現在當區塊中的字符僅僅映射到"卻省"或"無法匹配"的字符時。不是使用 空指針NULL和一個卻省值,而是創建了一個卻省項的"共享"塊。由於避免使用測試和分支,這種策略可以提供接近於簡單數租訪問的速度,卻大大節省了存儲 空間。
(6)多級表調節(Multistage Table Tuning)
給定一個具有任意大小和內容的表,可以較容易的創建一個小的應用程序,來計算多級表的最佳級數和它們的寬度。通過調節級數和它們的索引指針數組的寬度,可以在表大小和平均訪問時間之間進行折衷。
4.2 ANSI/ISO C wchar_t
在ANSI/ISO C中,爲固定寬度的寬字符定義了類型wchar_t,ANSI/ISO C將寬字符集語義的定義留給了特定的實現。
wchar_t的寬度是由編譯器指明的,可以只有8位大小。因此,需要在不同C或C++編譯器間可移植的程序不應該使用wchar_t存儲Unicode文本。
對 於UTF-16的實現,可以使用宏macro或者類型定義typedef(如UNICHAR),編譯爲unsigned short或者wchar_t(依賴於目標編譯器和平臺)。對UTF-32的實現可以使用編譯爲unsigned int或wchar_t的宏或者是類型定義。這樣的選擇使在不同的系統平臺和編譯其中可以正確編譯。
4.3 未知和缺少的字符(Unknown and Missing Characters)
4.3.1 保留的和私用的字符編碼(Reserved and Private-Use Character Codes)
有兩類碼點,即使是完全的Unicode標準實現也無法正確解釋:
 被保留的碼點;
 在私用區中的碼點。
一個實現不應試圖去解釋這樣的碼點。然而,在實際中,應用程序必須處理爲分配的碼點或私用字符。例如,當應用程序所處理的文本是由一個實現更新版本的Unicode標準的系統創建的,其中包含更多的分配字符。
對未知字符顯示的選擇包括將碼點顯示爲四到六位十六進制數字,顯示一個黑得或白的方塊,針對保留字符和私用字符分別顯示適合的字形,或者什麼都不顯示。一個實現不能刪除這樣的字符,也不能無目的地轉換爲其他字符。
4.3.2可解釋但無法顯示的字符(Interpretable but Unrenderable Character)
一個實現可能接收一個分配給Unicode字符的碼點,但無法顯示它,因爲沒有字體或者無法正確顯示。
在這種情況下,實現可能會對用戶的詢問提供進一步有限的反饋,如對數據進行適當的排序,顯示它的書寫系統,或者以卻省放時顯示碼點。對無法顯示的(但是已分配的)碼點和未分配的碼點,實現可以通過爲無法顯示的碼點使用指示類別的不同字形表示。
4.3.3卻省的屬性值(Default Property Value)
要使實現可以正常工作,需要把未分配的碼點看作字符分配卻省的屬性值,因爲各種算法都需要分配給每個碼點的屬性值來運作。這些卻省值不是對所有未分配的碼點都相同,因爲碼點中的某些範圍需要不同的屬性值以便與將來期望的分配做到最大兼容。
除非被特指,卻省屬性值不是標準的,具有一致性的實現可以使用其他值。例如,取代卻省值,實現可能使用以下規則,爲一塊未分配字符插入相鄰已分配字符的屬性值。
 注意在兩個方向上最接近的已分配字符,如果它們處在相同的塊中具有相同的屬性值,則使用這些值。
 從任一區塊的邊界開始,一直擴展到塊內最近的已分配字符處爲止,使用區塊中字符對應的屬性值。
 如果所有的碼點完全位於空的或未分配的塊中,使用對應屬性的卻省值。
4.3.4卻省的可忽略的碼點(Default Ignorable Code Points)
一 般,在可支持字符集外的碼點使用一個應變的字形顯示,如一個黑方塊。然而,格式和控制字符不應該由可見的字形(儘管它們對其他字符的顯示有影響)。除非對 於一些特定的處理,這些字符也被忽略,例如,字符ZERO WIDTH NON-JOINER在對照(collation)中忽略。爲在不同版本的標準間保證最大程度的兼容性,範圍U+2060到U+206F,U+FFF0到 U+FFFB,和U+E0000到U+E0FFF保留給格式和控制字符。在這些範圍中的位分配碼點應該在處理和顯示中被忽略。
4.4 處理UTF-16中的代理對(Handling Surrogate Pairs in UTF-16)
在形式良好的UTF-16中,在一個低代理碼點之前只能是一個高代理碼點,而不能是另一個低代理碼點、一個非代理碼點或者是文本的開頭。一個高代理碼點的後面也只能跟一個低代理碼點,而不能是另一個高代理碼點、一個非代理碼點或者是文本的結尾。
高代理碼點和低代理碼點被分配了不相交的編碼單元,非代理的碼點也不會使用這些範圍內的編碼單元值表示。因此,在形式良好的UTF-16中的每個編碼單元必須只滿足下面三個可能的條件之一:
 一個單一的非代理編碼單元表示的碼點範圍是0到D7FF或E000到FFFF;
 一個高代理碼點表示代理對的第一部分;
 一個低代理碼點表示代理對的第二部分。
最多訪問兩個編碼單元,使用UTF-16編碼格式的處理過程就可以解釋任何Unicode字符。確定字符邊界最多只需要掃描前一個或後一個編碼單元,而不需考慮其他部分。
只要實現不去除代理對中的任一編碼單元,或者在代理對中兩個編碼單元間錯誤的插入另一個字符,就可以保證數據的完整性。而且,即便數據被破壞了,錯誤也是局部的。
UTF-16具有非常有利的頻率分佈,在所有文本數據中的大多數部分中,代理對非常罕見,非代理碼點將非常普遍。這不僅有利於減少由於處理變長編碼而帶來的性能損失,也允許一些處理過程可以不對代理對採取特別的操作,或者使用已有處理字符序列的機制來處理代理對。
實現必須在處理UTF-16文本時完全支持代理對。但是,實現中的單獨的組件可以具有對代理對不同程度的支持,只要這些組件之間可以正確的組合和交流。對代理對不同程度的支持由兩個主要方面決定:
 實現是否解釋增補的字符?
 實現是否保證代理對的完整性?
Surrogate Support Levels
Support Level Interpretation Interity of Pairs
None No supplementary characters Does not guarantee
Transparent No supplementary characters Guarantees
Weak Some supplementary characters Does not guarantee
Strong Some supplementary characters Guarantees
不支持代理對,實現就不會對任何增補字符進行解釋,也不保證代理對的完整性。
透 明的代理對支持(transparent surrogate support),用於這樣的組件,如編碼格式轉換,它可能完全保證對代理對的正確處理,但不解釋任何增補字符。也適用於低層串處理操作的組件,一個 Unicode串只是簡單地作爲編碼單元的數組而不顧它們的代理狀態,不對串進行解釋。
不充分的代理支持(weak surrogate support)只正確地處理那些對應可解釋字符的代理對,可能調用的組件被保證不會傳遞無法解釋的字符。
支持代理對的策略(Strategies for Surrogate Pair Support)
   處理Unicode標準中高級特性的一些實現可以很容易地被改進,來支持UTF-16的代理對。例如:
 在文本對照(text collation)中可以把代理對作爲"組合字符"來處理。
 文本的輸入可以使用一次按鍵產生兩個Unicode碼點的鍵盤來完成,就如一次ENTRE鍵可以生成CRLF或者在阿拉伯鍵盤上的"lam-alef"可以生成兩個字符lam和alef的序列。
 文本截斷(truncation)可以使用與保證組合標記緊跟基字符相同的機制。
如 果文本編輯器可以保證插入點(insertion point)位於字符邊界,就可以阻止用戶破壞文本。只要使用文本元素邊界,低層的串處理程序(如wcschr)就不用進行修改。實際上,只有某些高層的 處理需要注意代理對;底層的例程可以繼續使用對16位編碼單元操作,而不需特別對待代理對。
4.5 處理數字(Handling Number)
在Unicode 中,有一些字符集合用於表示不同書寫系統中的十進制數字。在數字上,解釋這些字符的系統必須提供正確的數字值。比如,在數字上,對序列<U+ 0968 DEVANAGARI DIGIT TWO, U+0966 DEVANAGARI DIGIT ZERO>解釋,具有值20。
當從二進制的數字值轉換爲可視的形式時,可以從不同的書寫系統中選擇數字。
ASCII數字的全角變形(fullwidth)僅是通常數字的兼容變形,應作爲一般的西文數字對待。
羅馬數字和東亞的表意字符數字也是十進制的數字書寫體系,但它們在形式上不是以10爲基數的數字系統。因此,不可能採用一對一的方式轉換成像123456.789的形式。
使用表意字符,也可能以兩種方法書寫數字。如數字1,234可以表示爲"一千二百三十四"或"一二三四"。在數字解析使支持這些數字意味着實現必須能區分這兩種情況。
有時候數字需要解析,但它們並不是數的一部分。例如由字母和數字組成的標示符。
只有在另一層上(如實現一個完整的數學公式解析器),對上標(superscripting)的解釋纔是至關重要的。
4.6 正規化(Normalization)
(1)可選擇的拼寫(Alternative Spelling)
在Unicode標準中對最常用的一些加重音符的字符分配明確的編碼。這些字符也可以通過組合獲得,對於加重音符的字母,可以由基字符和非間距標記(nonspacing mark)組合而來。
Unicode標準提供對可由基字符加一個或多個非間距標記組合而來字符的分解。分解映射與特定Unicode標準的版本有關。
(2)正規化(Normalization)
系統可能會將Unicode編碼格式的文本正規化爲特定的序列,如將組合字符序列正規化爲由預組合字符的序列,或者相反。
無法處理非間距標記的系統,可以正規化爲預組合字符,適用於大多數基於拉丁語的現代語言。對於無法處理的組合字符,系統可以使用替代顯示方法,至少在顯示上表示組合。
對可以處理非間距標記的系統,執行正規化消除預組合字符可能會有用,使系統對組合字符有統一的表示,保持對這類字符處理的一致性。
4.7 壓縮(Compression)
   使用Unicode字符編碼可能會增加用於保存文件文本部分的存儲和內存空間。因此,對Unicode文件或串進行壓縮是一個很好的選擇。壓縮往往建立一個更高層的協議,並且依賴於所使用的壓縮方法的知識進行交換。
4.8 換行的原則(Newline Guidelines)
換 行符在不同的平臺上表示爲:carriage return(CR)、line feed(LF)、CRLF,或next line(NEL)。不僅換行符使用不同的字符表示,並且在相同平臺上,它們也具有不明確的行爲。當轉換字符集編碼時,這些字符通常被直接轉換爲對應的 Unicode碼點。這意味着,即使是處理純Unicode文本的程序也必須解決這些問題。特別是隨着Web的出現,在一臺機子上的文本可能具有不同的來 源,將引起很大問題。
換行符用來明確指示行的邊界。
4.8.1 定義(Definitions)
Hex Values for Acronyms
Acronym Name Unicode ASCII
CR carriage return 000D 0D
LF line feed 000A 0A
CRLF carriage return and line feed 000D,000A 0D,0A
NEL next line 0085 85
VT vertical tab 000B 0B
FF form feed 000C 0C
LS line separator 2028 n/a
PS paragraph separator 2029 n/a
在Unicode標準中,沒有正式地分配控制字符,而是爲各種7位和8位字符編碼標準中使用控制字符提供相應的碼點。確保了Unicode標準與其他編碼標準的相關性和相互映射。
縮寫NLF(newline function)表示針對一個新行分隔符的一般控制功能。
4.8.2 背景(Background)
段落分隔符(paragraph separator)用於指示段落之間的分隔。行分隔符(line separator)指示在何處進行斷行,特別是在一個段落中。
記錄分隔符(record separator)用於分隔記錄。例如,當交換表格式數據時,一種普通的格式是使用TAB分隔單元和在一行單元后使用CRLF。儘管這種功能與行分隔不是正好相同,但使用了同樣的字符。
NLF開始時作爲行分隔符。現在,在一些簡單的文本編輯器中還作爲行的分隔符。隨着平臺和程序開始使用自動分行進行字處理,這些字符被用於表示段落分隔符。
一旦NLF被用來表示段落分隔符,在一些情況下,另一個控制字符就被作爲行分隔符使用。例如,在Microsoft Word中,就使用vertical tabulation(VT)。
4.8.3 建議(Recommendation)
在Unicode 中,定義了兩個明確的分隔字符:U+2029 PARAGRAPH SEPARATOR(PS)和U+2028 LINE SEPARATOR(LS)。在Unicode文本中,應該在所表達功能明確的地方使用PS和LS字符。否則,當從其他字符集轉換爲Unicode時,當 解釋文本中的字符時,和當從Unicode轉換爲其他字符集時,使用以下規則處理NLF。
即使實現知道在一個特定的平臺上用哪個字符表示NLF,在輸入和解釋時CR、LF、CRLF和NEL應該被相同對待。只要在輸出時,纔有必要進行區分。
(1)從其他字符編碼集轉換
R1 如果知道NLF的確切的用法,則轉換爲LS或PS。
R1a 如果不知道NLF的確切用法,則映射爲與平臺對應的NFL。
(2)解釋文本中的字符
R2 總把PS解釋爲段落間隔,把LS解釋爲行間隔。
R2a 在字處理中,把任一NLF都解釋爲PS。
R2b 在簡單文本編輯中,把任一NLF都解釋爲LS。
R2c 在解析中選擇最安全的解釋。
例如,對R2c,涉及斷句啓發規則的實現會按照以下方法,將NLF安全的解釋爲LS:
 當一個NLF應是PS時,假設把它解釋爲LS。因爲多數段落總是以標點符號結束,這只會在個別情況造成對句子邊界的錯誤識別。
 當一個NLF應是LS時,假設把它解釋爲PS。在這種情況下,行分隔符將是句子斷開,對斷句啓發規則帶來很大錯誤。
(3)轉換爲其他字符編碼集
R3 如果已知轉換的目標,根據目標協定,適當地對NLF、LS和PS進行映射。
例如,當映射爲Microsoft Word對文檔的內部協定時,LS將映射爲VT,PS和其他NLF將映射爲CRLF。
R3a 如果不知道轉換的目標,將NLF、LS和PS映射到平臺的換行協定。
(4)輸入和輸出
R4 函數readline應該在遇到NLF、LS、FF或PS時停止。在典型的實現中,不包括停止位置的NLF、LS、FF或PS。
因爲分隔符會丟失,對這種readline函數的使用僅限於與分隔符的類型無關的文本處理。
R4a 函數writeline應該根據(3)中的協議轉換NLF、LS和PS。
(5)頁面分隔符
FF一般用作頁面分隔符,在文本中應該按照情況解釋。當在屏幕上顯示時,在分隔符後的文本會被強制放如下一頁。它與段落分隔符無關:一個段落可以在一頁開始在下一頁中繼續。除非是在頁面中顯示,在大多數解析過程和readline中,與LS的解釋相同。
4.9 正則表達式(Regular Expressions)
面向字節的正則表達式工具需要擴展以正確處理Unicode。下面是擴展所涉及方面:
 Unicode是一個很大的字符集,只適用於處理小字符集的正則表達式工具可能無法調整。
 Unicode包括多種語言,它們具有與英語或其他西歐語言非常不同特性。
4.10 純文本中的語言信息(Language Information in Plain Text)
4.10.1 語言標記的需要
在純文本數據中嵌入語言信息的需要經常被誇大。一些普通操作,如對照(collation)很少需要這些額外信息。
然 而,語言信息對某些操作非常有用,如對一個混合語言的文檔執行拼寫檢查或者連字(hyphenating)。對於爲無格式文本選擇卻省字體也非常有用,例 如日文字體中的省略符號具有與英文字體不同的外觀。當前的字體和佈局(layout)技術基於語言信息產生不同結果。儘管語言信息對於執行文本-語音轉換 (text-to-speech)操作有用,但當前的文本-語音轉換軟件都必須對文本執行非常複雜的語法分析,因此確定語言的額外工作就不那麼重要了。
語言信息可以使用帶外信息(out-of-band)或內嵌標記(inline tag)表示。在內部實現中,通常使用帶外信息,保存在與文本並聯的數據結構中,而不是嵌入到文本數據中。帶外信息不影響對文本的正常處理,還可以輕鬆的支持對文本的操作。
4.10.2 語言標記與漢字統一
對Unicode中漢字統一的一個常見誤解是覺得沒有語言信息就無法正確顯示漢字字符。其實,漢字統一的目標和方法是確保文本可讀。儘管需要添加字體、大小、寬度和其他格式規格,以便在源和目標機器上準確產生相同的外觀,但在沒有這些規格時,純文本也能保證可讀。
因爲不同國家所使用的統一的漢字間的不同,都僅限於格式上的變化,不會引起Unicode中的混亂。在Unicode中的漢字統一不會使讀者音唯一不同的字體顯示而無法識別一個字符。如果準確的字體信息很重要,最好使用格式文本。
4.11 編輯和選擇(Editing and Selection)
一致的文本元素(Consistent Text Elements)
從 用戶的角度,文本的基本表示不是所關心的,但重要的是,編輯接口必須對用戶所認爲的字符提供一個統一的實現。用戶希望在鼠標選擇、方向鍵移動、退格等操作 中,這些字符表現得像一個個單元。例如,當實現這些行爲後,對一個表示爲基字符加非間距組合標記序列的加重音符字母,使用右移方向鍵時,邏輯上會從基字符 的開始跳到最後一個非間距字符後面。
在詞中的編輯和選擇,一般有三種類型的邊界(boundary)。
簇邊界(cluster boundary)
任意定義的簇邊界可能會出現在像梵文(Devanagari)這樣的書寫系統中,選擇操作可能會應用於音節或者音節的一部分。在這種情況下,組合字符序列,如ka+vowel sign或者聯合的簇ka+halant+ta,作爲單一的單元選擇。
堆疊字符邊界(stacked boundary)
堆疊字符邊界一般比簇邊界更細。獨立的元素(如梵文vowel sign a)可以不受約束的選擇,但是任何堆疊在一起的字符(包括垂直連字符,如阿拉伯文中的lam+meem)只能作爲單一的單元選擇。
原子字符邊界(atomic character boundary)
原 子字符邊界的使用最接近於單個Unicode字符的選擇。然而,大多數當前系統都採用某種矩形加亮的方式表示選擇操作。這種方法限制了編輯操作的一致性, 因爲一些字符序列不是從行的起始處成直線地發展。當字符堆疊時,兩種機制被用於對部分選擇地顯示:直線的和非直線的邊界。
直線的邊界(linear boundary)
使用直線邊界,將合成字形的全部寬度都歸屬於序列的第一個字符,認爲其餘字符沒有寬度。
這是最簡單的一種機制。它的優點是只需要很少的額外實現工作。它的缺點是選擇窄字符變得非常困難,更不用說零寬度的字符。需要用戶剛好從非間距標記右邊開始選擇,並且正好拖到左邊。如果有多個非間距標記,它也不允許對單個標記進行選擇。
非直線的邊界(nonlinear boundary)
使用非直線邊界把任何堆疊字符分成各個部分。可以通過對多個矩形加亮,或者對單個字符着色的方法進行表示。
注意到,通過更多的操作,一個預組合的字符在刪除操作中可以表現得像一個具有原子字符邊界組合字符序列一樣。這個過程包括動態地獲得字符的分解表示,得到用作模擬的組件。
在多數系統中,字符時文本中最小的可尋址單元,所以選擇操作和屬性分配操作(如字體、顏色、字符間距等)都在字符的基礎上執行。對於預組合地字符無法模擬這種可尋址性,系統地修改所有文本編輯工具來對字符的一部分進行尋址,會十分低效。
由 於文本元素不具有一個單一的概念,因此,對字符邊界的編輯也沒有一個統一的概念。在不同情況下,用戶可能會在編輯過程中使用不同程度的粒度大小。可以考慮 兩種方法:首先,用戶可能設定對字符邊界的一個全局偏好;第二,用戶可能有可選的命令機制,如Shift-Delete,可以提供對卻省模式更細(或更 粗)的控制。
4.12 處理非間距標記的策略
依據一下策略,開發者可以實現對非字符間距有效和高效使用的系統和例程。開發者也可以選擇適用於絕大多數已有系統的最小限度的技術,和適用於要求更苛刻的情況的複雜技術,如高端的桌面出版。
在 這裏,術語非間距標記(nonspacing mark)和組合字符(combining character)可以互換使用。有時會使用術語diacritic、accent、stress mark、Hebrew point、Arabic vowel等,而不是非間距標記(它們表示特定類型的非間距標記)。
爲支持非間距標記,只需要相對較小數量的實現特性。存在多種可能層次的實現。一個最小的系統可以產生較好的結果,並且相對容易實現。要求大多數特性地系統,只是對已有軟件地簡單修改。
因爲有一些語言要求非間距標記,如Arabic、Hebrew和印度次大陸的語言,已有一些可以處理這些字符的系統,可以利用已有經驗來生成處理Unicode標準中這些字符的多用途軟件。
顯示(rendering)
一 部分確定的組合字符序列可以通過簡單的替換來有效顯示。當遇到一個有基字符加一個或多個非間距組合標記組成的序列時,可以使用表示組合形式的字形進行替 換。在簡單地字符顯示中,一個非間距組合標記不增加寬度,一個組合字符序列的具有與基字符相同的寬度。當截斷串時,從結尾處開始向後執行截斷總是最容易。 後續的非間距標記將不會與前面的基字符分開。
一個更復雜得顯示系統會考慮使用非間距標記時對寬度和字距更細微的調整,或者組合字符序列具有與基字符不同寬度。對大多數應用而言,這樣地顯示系統並不是必需的。
其他處理:正確的多語言比較例程也必須能夠把字符序列作爲一個字符比較,或者把一個字符看作是一個字符序列。只要提供了適當的數據,這些例程也能處理組合字符序列。當查詢串時,要檢查目標串中可能會影響最後一個匹配字符解釋的附加非間距標記。
斷行算法一般使用狀態機,確定詞間的中斷。這樣的算法可以很容易地改進,來阻止將非間距標記從基字符分開。
鍵盤輸入(Keyboard Input)
用 於組合字符序列輸入的一個常見實現,是使用所謂的dead key。這些鍵與打字機生成這樣序列所使用的機制匹配,通過在非間距標記之後鍵入基字符。在計算機的實現中,當按下針對重音符的dead key時鍵盤進入一種特殊的狀態,只有當鍵入一些有限數目的"合法"基字符之一時產生一個預組合的字符。根據需要,可以改進系統來生成組合字符序列或者預 組合的字符。儘管打字員,特別是使用Latin書寫系統的,是針對這類系統培訓的,然而在Unicode標準中一些書寫系統(包括Latin)可能會依據 書寫的順序來實現,用戶首先鍵入基字符,其後跟着重音符或其他非間距標記。
在書寫順序的情況下,每一次鍵入都在屏幕上產生一個不同的自然變化。要給已有的字符添加重音符,用戶需要把插入點移到字符後在鍵入重音符。
截斷(Truncation)
有兩種類型的階段:根據字符數目截斷和根據顯示寬度截斷。根據字符數目截斷可能帶來數據損失,也可以是無損失的。
根據字符數目進行截斷使用在,由於存儲限制,只有有限數目的字符可以放入某區域;也用於,爲了傳送和其他目的將文本插入緩衝區中。在後一種情況下,如果在處理前緩衝區中的數據可以無縫的重新組合,或者預先檢查一下可能出現的跨緩衝區組合字符序列,就可以做到不丟失數據。
當調整數據以適應有現長度的區域時,一些信息將會丟失。在文本邊界上進行截斷(例如,在組合字符序列的最後或者在最後一個詞邊界)通常比在最後一個碼點後截斷更可取。
根據顯示寬度截取用於有限範圍內的可視顯示。在這種情況下,截斷是依據結果串的寬度而不是字符的數目。在簡單的系統中,依據寬度截斷很容易,從末尾處開始向後操作減去字符的寬度。由於後續非間距標記對串的尺寸沒有貢獻,最後結果不會把非間距標記與它們的基字符分開。
如果文本環境會更復雜,字符的寬度可能會依賴上下文環境,由於字符間距調整、連字或上下文信息等的作用。對這種系統,一個組合字符的寬度可能會與一個單獨的窄字符(如i)的寬度不同。處理這種情況,必須對截斷結果進行覈查。
一個不同的選擇是在圖形上對字符進行修剪。但不幸的是,結果可能很難看。並且,如果修剪出現在字符之間,可能不會給出任何世界反饋表示字符被刪除了。
4.13 非間距標記的顯示(Rendering Nonspacing Marks)
在這裏假定使用均衡字體(proportional font),單個字符的寬度可以變化。對於等寬字體(monospaced font),可以使用各種技術,但一般而言,對於這種字體的多數書寫系統,可能只有一種正確的顯示外觀。
當 顯示的序列中包含多於一個的非間距標記時,卻省情況下,非間距標記從基字符向外堆疊。即,如果亮格非間距標記出現在基字符的之上,則第一個非間距標記位於 基字符上面,第二個非間距標記爲與第一個標記上面。如果亮格非間距標記出現在基字符的之下,則第一個非間距標記位於基字符下面,第二個非間距標記爲與第一 個標記下面。
這種卻省行爲可能會根據排字上的偏好,或者某個特定書寫系統中對多個非間距標記的特定正字法處理,而改變。
後退的顯示(fallback rendering)
有幾個方法可用於處理在一個固定的可顯示集合外未知的組合字符序列。
一種方法是Show Hidden,通過先顯示基字符再把非間距標記作爲單個單元顯示,來表示無法描繪序列。
另一種方法是Simple Overlap,將重疊的零寬度非間距標記放置在卻省的固定位置處,一般所放置的位置例可能的基字符較遠。儘管顯示結果對於一些字母而言沒有吸引力,但在只有一個非間距標記的情況下,結果一般還是可以辨認的。
在一個退化的情況下,一個非間距標記作爲文本的首字符出現,或者被行分隔符、段落分隔符或其他引起位置分隔的格式符從它的基字符分開。這種結果稱爲不良的組合字符序列。不良的組合字符序列在顯示時,看作是以一個空格作爲基字符。
雙向定位(bidirectional positioning)
在雙向文本中,非間距標記與它們的基字符一起重新排序。即視覺上,在使用雙向算法之後它們應用於相同的基字符。
調整(justification)
典型地,對文本的完全調整要給間距字符(space character)添加額外的空間;然而,如果只有很少(或沒有)間距字符,一些系統會在字符間添加額外的字間隔空(letterspacing)。如果在文本中包含零寬度的非間距標記,則需要對該過程進行改進。
因爲非間距標記總是跟隨它們的基字符,正確的調整過程應該只有當第二個字符是一個基字符時纔會在字符見添加字間隔空。
規範等價性(Canonical Equivalence)
在 顯示多個重音符時,必須考慮規範等價性,以便使任兩個規範等價的序列顯示結果相同。這一點在當規範順序與習慣的鍵盤輸入順序不相同時特別重要,如具有元音 符號的阿拉伯文和使用點的希伯萊文。在這些情況下,顯示系統得到的是典型的鍵入順序或者是經過正規化(normalization)的規範順序。
顯示系統應該處理組合標記的任何具有規範等價性的序列。這不會有性能問題,因爲對組合標記重新排序所需的時間與其他顯示工作的耗時相比微不足道。
一個顯示系統,在需要時,可以在內部對標記重新排序,只要結果序列是規範等價的。
定位方法(Positioning Methods)
有一些方法可用於定位非間距標記,使它們相對於基字符和前一個非間距標記(如果有的話)的位置正確。
使用連字(positioning with Ligature)
一 個固定範圍的組合字符序列可以使用相對簡單的替換來有效顯示。當字形可以表示一個序列<基字符,非間距標記>時,使用這個字形替換組合形式。 因爲非間距標記的擴展寬度爲零,組合字符序列將自動具有與基字符相同的寬度。跟複雜的文本顯示系統可能會採取進一步的措施來處理一些特殊情況,如組合字符 序列的緊排(kern)或者寬度與基字符不同。
使用連字可能是支持非間距標記最簡單的方法。對於較小的固定字集,如那些對應ISO/IEC 8859-1(Latin-1)重預組合字符的,可以直接採用該方法。因爲組合字符序列幾乎總是具有與基字符相同的寬度,對這些字符的顯示、測量和編輯與 一般連字的情況相比都更容易。
如果組合字符序列不能形成一個連字,就需要採用以下兩種方法之一。如果這些方法都不可用,則使用後退的方法。
根據上下文結構定位(positioning with contextual forms)
處理非間距標記定位的一個較通用的方法是使用上下文的結構。在這種情況下,有幾個不同的字形對應於重音符的不同位置。依據大致的形狀和寬度,基字形(基字符的字形?)通常分成數目較小的一些類別。根據基字形的類別,爲非間距標記選擇一個特定的字形。
在一般情況下,可以從一些具有不同高度的字形中進行選擇,以便堆疊字形。這種方法可以與使用連字的方法結合使用,就可在特定情況下,使用連字生成更高的變形。
使用增強的字距調整(positioning with enhanced kerning)
第三種用於定位讀音符號的技術是對常規的字距調整(水平的和垂直的)的擴充。典型地,字距調整過程唯一對字形映射一個位置偏移量。例如,在詞語"To"中,"o"應該向"T"下面靠一點。這種系統的擴充則分別映射一個垂直的和水平的偏移量。
爲了針對一般情況可以有效應用,字距調整過程也必須能夠處理比簡單字符對更復雜的情況,如在一個基字符後可能有多個讀音符號。
使用增強的字句調整技術進行定位,也可以和使用連字的方法結合運用。
4.14 定位文本元素邊界(Locating Text Element Boundaries)
Unicode 編碼的文本串經常需要被分解爲文本元素。文本元素的一般例子包括字符、詞、行和句子。文本元素的準確確定可能會依據地區而變化。但要與用戶的理解相匹配並 不是總能達到的,因爲文本本身並不總是包含足夠的信息用於明確決定邊界。例如,句點"."(U+002E FULL STOP)的使用具有歧義,有使用於表示句子結束,有時用於縮寫,有時則用於數字。然而,在多數情況下,文本邊界可以符合用戶的理解。
4.15 標識符(Identifiers)
Unicode 標準的實現面臨的一個常見任務是提供針對標識符的解析工具。爲了促進在基於Unicode字符的解析器中對標識符的標準化處理,這裏針對標識符語法的定義 提出一套指導方針。這些指導方針並不比普通程序設計語言中規則更復雜,只不過包含了更多具有不同類型的字符。
基於屬性的標識符語法(property-based identifier syntax)
這 裏提供的正式語法就是要明確,一個標識符是由一個字母或者一個表意字符開始,包含任意數目的字母、表意字符、數字或下劃線的字符串組成的。每種程序設計語 言標準都有自己的標識符語法,不同程序設計語言對ASCII範圍內特定字符的使用有不同的約定。對這些語法進行擴充以具備Unicode實現的全部行爲, 只需要講這些特定規則與下面提供的樣本語法結合。
爲了正確的涵蓋Unicode標準,樣本標識符語法中的革新之處包括:
 結合對組合標記的恰當處理。
 允許有佈局和格式控制字符,在解析標識符時忽略。
組合標記(combining marks)
標識符語法中必須考慮組合標記。由一個基字符跟隨若干組合標記組成組合字符序列對一個標識符而言是有效的。
封閉的組合標記被排除在<ident_extend>的語法定義外,因爲由它們和字母所組合得到的組合字符不是這些標識符有效的組成部分。
佈局和格式控制字符(layout and format control character)
用 於控制組合行爲,雙向順序控制和可選顯示格式的Unicode字符,被明確定義爲不影響中斷行爲。不像空格符或其他分隔符,它們不用來指示詞、行或其他單 元的邊界。因而,爲了標識符定義,將它們明確包括在內。一些實現可能選擇過濾掉這些可忽略字符,這種方法的優點在於兩個顯示相同的標識符更可能是相同的。
特殊字符調整(specific character adjustments)
特殊的標識符語法可以被看作是基於字符屬性對普通語法的少量修改。例如, SQL標識符允許下劃線作爲標識符的一部分(但不能作爲開始字符);而C標識符允許既下劃線作爲標識符的一部分也可以作爲標識符的開始字符。
可以考慮排除在標識符外的字符集合包括所有兼容映射具有<font>標記的字符。
語法規則(Synactic Rule)
<identifier> := <identifier_start> (<identifier_start>|
<identifier_entent>)*
Sytactic Classes for Identifiers

Syntactic Class Properties
<identifier_start> General Category = L or Nl, or
Other_ID_Start = true
<identifier_extend> General Category = Mn, Mc, or Nd, Pc, or Cf
可選建議(Alternative Recommendation)
使用語法類別不足之處是,用於詳細定義的存儲空間,以及隨着新版本Unicode標準添加的新字符無法被已有的解析器識別。也就是說,無法做到向上兼容。
解決該問題的一個方法是,不去定義允許使用的碼點集合,而是將一個較小的固定的碼點集合保留給語法使用並且允許使用其他任何碼點(包括非分配的碼點)用作標識符的一部分。按照這種規範編寫的解析器對任何版本的Unicode標準得表現相同。
這種方法的缺點是標識符中部分可能是沒有意義的東西,因爲將詞彙分類與人類的可理解性分開了。然而,可理解性可以通過其他方法解決,如使用用法指南限定使用有意義的術語。例如W3C指定的規範XML 1.1。
通 過增加不允許使用字符的集合,可以得到針對標識符較直觀的建議。這種方法使用Unicode標準一個特定版本中關於標識符類別的所有規範,並且永遠不允許 使用該版本中不推薦用作標識符的字符。該版本Unicode標準中沒有分配的所有碼點可用於標識符,已經考慮到將來對版本的添加。這種方法保證了向上兼容 的標識符穩定性,以及將字符合理地劃分爲具有或不具有意義的標識符組成。
可以對禁止使用的碼點列表進行一些額外的擴充,來進一步限制不合理的標識符。
4.16 排序和查找
排 序和查找操作部分相一致,都要實現相互比較項的等價程度判定。在查找操作中,等價定義項是否匹配;在排序操作中,等價影響項在有序隊列中的鄰近。等價的確 定經常依賴於應用和語言,但對於支持Unicode標準的實現而言,排序和查找必須考慮到Unicode字符的等價性和規範順序。
與語言文化有關的排序和查找
排 序順序隨着文化的不同而變化,並且一些特殊的應用需要變化。排序的順序可以依據詞或者句子,區分大小寫或者不分大小寫,忽略重音符或者不忽略;也可以是依 據語音,或者基於字符的外觀,比如使用筆劃和部首對東亞的表意字符排序。對漢字的語音排序需要使用詞語的查找詞典,或者是可以維持文本中詞和相關語音拼寫 的特殊程序。
語言不僅決定使用哪一種排序,而且決定什麼構成排序的基本元素。例如,瑞典語中將U+00C4 LATINE CAPITAL LETTER A WITH DIAERESIS作爲一個單獨的字母,在字母表中排在z之後;然而,在德語中,則作爲ae或者識跟隨在a之後的其他重音形式。西班牙語在傳統上將連字 ll看作在l和m之間的字母來排序。
因此,不可能在編碼時以某種順序安排字符以便通過簡單的二進制串比交接可以生成期待的順序,也不可能提供單級的排序權重表。後者意味着字符編碼細節對文化上期待的排序只具有間接的影響。
與語言無關的排序
在 一些環境下,應用程序可能需要進行與語言無關的排序,即對文本數據排序,而不考慮針對串如何排序的與語言相關的文化期望。例如,一個臨時的索引可能只需要 以某些定義良好的順序排列,但排序的準確細節並不重要或者對用戶不可見。然而,即使在這種情況下,也需要注意一些問題。
首先,三種Unicode編碼格式的二進制排序存在一些細微的差別。只需要對Unicode串進行二進制比較的實現必須考慮這一點,不至於在使用不同編碼格式的應用程序間引起互操作問題。
一些排序或者查找應用,即使不關心排序中與語言相關的差別,也要求與大小寫無關。傳統上,執行與大小寫無關比較的實現是通過在二進制比較前將兩個串都轉換爲大寫的形式來完成的。然而,這種方法一般不能擴展到Unicode標準中的所有字符。
查找
查找也受比較操作中一些同樣的問題影響。也增加了其他一些特徵,如只匹配詞(即在匹配的兩邊都是詞的邊界)。一種技術是針對一個弱匹配進行快速查找。當發現一個候選匹配時,根據其他標準(如匹配變音符,詞匹配,大小寫匹配等等)。
當 查找串時,必須檢查目標串中尾隨的非間距標記,可能影響最後一個匹配字符的解釋。也就是,查找"San Jose"可能會在串"Visiting San José, Costa Rica is a ..."發現一個匹配。如果要求準確的匹配,則應該否決該匹配。如果只要求弱匹配,則可以接受該匹配,但是在返回目標字串的位置和長度時必須包括尾隨的非 間距標記。
弱等價的一個重要應用是與大小寫無關的檢索。一些傳統的實現將查找串和目標串都映射爲大寫。然而,大小寫映射是依賴語言的,並且不是沒有歧義。
因爲從外部字符集的錯誤映射,產生一個相關問題。爲了解決這個問題,可以將用戶易搞混的字符歸爲一個弱匹配類。這種方法在查找命名的文件或其他對象時可以更好的滿足用戶的語氣。
次線性查找(Sublinear Searching)
使用比較信息,通過硬算(brute force),國際化的查找是可能的。然而,這種策略在最壞情況下需要O(m*n)算法,在一般情況下需要O(m)算法,n是所尋找的模式中字符的數目,m是目標串中的字符數。
一些算法可以使用次線性的算法對簡單文本進行快速查找。通過在目標串中跳過字符,這些算法在通常情況下的複雜度只有O(m/n)。
在次線性查找中採用與語言有關的比較算法的主要問題,與多映射和可忽略有關。另外,次線性算法預先計算信息表。
4.17 二進制順序
如果比較文本對最終用戶是可見的,就應該使用正確的語言排序。然而,在有一些情況下,只需要一個快速的有良好定義的排序。在這種情況下,可以使用一個二進制排序。
Unicode 中的所有編碼格式並沒有相同的二進制順序。UTF-8和UTF-32的數據以碼點順序排序,而UTF-16的數據(碼點高於U+FFFF)則不是。而且, 當UTF-16或UTF-32數據使用某個Unicode模式序列化,並以字節比較時,得到的字節序列可能具有也可能沒有相同的二進制排序,因爲交換字節 順序將影響數據的大體排序。由於這些因素,UTF-16BE、UTF-16LE、UTF-32LE編碼方案下的文本不是以碼點順序排序。
一般,Unicode文本的卻省二進制排列順序應該是碼點順序。然而,可能需要與特定編碼格式中的編碼單元順序(或是特定編碼方案的字節排序)匹配,以便完成不同應用中使用的排序。
4.18 Case Mapping
Case 是特定字母表中字符的一個標準屬性,比如Latin、Greek、Cyrillic、Armenian,和古代格魯吉亞文,字符被認爲是單個字母的變體。 這些變體在形狀和大小上可能區別很大,稱爲大寫字母和小寫字母。一般大寫字母比小寫字母大。具有大小寫差異的字母表稱爲bicameral;沒有的則稱爲 unicameral。
爲了兼容性還包含了某些組合字符,如U+01F1 "DZ" LATIN LETTER DZ,就有了第三種狀態,稱作titlecase,用於當詞的第一個字符被大寫時。這種字符的一個例子是U+01F2 "Dz" LATIN CAPITAL LETTER D WITH SMALL LETTER Z。
因此,三種狀態形式爲UPPERCASE、Titlecase和lowercase。
術語"titlecase"可用於指詞語,它的第一個字母是一個大寫字母或者是titlecase字母,其餘字母爲小寫。然而,並不是所有在文檔標題中的詞或者句子中的第一個詞都是titlecase。
決 定哪一個詞是titlecase依賴於語言。例如"Taming of the Shrew"在英語中是適當的大寫,但"Taming Of The Shrew"不是。而且,決定什麼真正組成一個詞是與語言相關的。例如,l'arbre在法語種可能被認爲是兩個詞,但can't在英語種被認爲是一個 詞。
Case Mapping的困難
一旦字符集超出了ASCII的範圍,case mapping就會有一些困難。
在多數情況下,titlecase與uppercase相同,但並不總是這樣。例如,U+01F1 "DZ" capital dz的titlecase是U+01F2 "Dz" capital d with small z。
case mapping可能生成與源串的長度不同的串。例如,德文字符U+00DF LATIN SMALL LETTER SHARP S在轉換成大寫時擴張成兩個字符的序列"SS"。這種情況也出現在沒有預組合字符的情況下。
由一些字符需要特殊的處理,如U+0345 combining iota subscript。
依 賴上下文環境,字符也可能有不同的case mapping。例如,U+03A3 GREEK CAPITAL LETTER SIGMA,當後面跟隨其他字母的時,對應的小寫字符爲U+03C3 GREEK SMALL LETTER SIGMA;沒有跟其他字母時,對應小寫字符爲U+03C2 GREEK SMALL LETTER FINAL SIGMAL。
字符的case mapping可能依賴於地區。
由於一些字母實際上不分大小寫,沒有匹配的大寫形式,因此,將一個串轉換爲大寫的過程並不意味着不包括任何小寫字母。
可逆性(Reversibility)
必須注意到,沒有case轉換操作時可逆的。例如:
toUpperCase(toLowerCase("John Brown")) -> "JOHN BROWN"
toLowerCase(toUpperCase("John Brown")) -> "john brown"
甚 至還有一些單個詞,像意大利語中的vederLa或英語中的名字McGowan,既不是大寫,也不是小寫或titlecase。這種形式有時稱作 inner-caps,通常用於程序設計和Web名稱。一旦串"McGowan"被轉換成大寫、小寫或titlecase,就不可能通過另一個大寫、小寫 或titlecase操作恢復原樣。也存在單個的字符沒有可逆的映射,如希臘文中的sigma。
對於使用單個命令鍵組成的序列在不同case間轉換所選擇內容的字處理軟件,建議保存初始串,並且可以通過鍵序列返回初始串。用戶界面要生成以下對一系列命令鍵響應的結果。注意,初始串每隔四次就會被存儲。
1. The quick brown
2. THE QUICK BROWN
3. the quick brown
4. The Quick Brown
5. The quick brown
在字處理軟件中,大寫、小寫和titlecase可以使用字符類型來表示。去除字符類型,就將文本恢復爲初始狀態。然而,如果採用這種方法,任何拼寫檢查軟件必須注意case類型,以便可以對真正的外觀進行檢查。
不分大小寫的匹配(Caseless Matching)
不分大小寫的匹配是使用case folding實現的,該過程將串映射爲一種消除了大小寫差異的規範形式。Case folding顧及到查找中的不分大小寫的快速匹配,因爲只需要二進制比較。它不僅僅是隻轉換爲小寫形式。
通常,初始的串不會被轉換的串替代,因爲這樣的替代可能會抹掉重要的信息。例如,名字"Marco di Silva"轉換爲"marco di silva",失去了關於哪個字母是大寫的信息。
在Unicode Character Database(UCD)中的文件CaseFolding.txt用於執行與地區無關的case folding。該文件是通過單字符映射和多字符映射,從UCD中的case mapping生成的。它將所有具有不同case形式的字符轉換成一個普通形式。對兩個串進行不分大小寫的比較時,可以利用這些數據對串進行轉換,在使用 二進制比較。


http://blog.chinaunix.net/uid-10468429-id-2953054.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章