热门问题
时间线
聊天
视角
國際化域名編碼
来自维基百科,自由的百科全书
Remove ads
國際化域名編碼[1](英語:Punycode)是一種表示統一碼和ASCII碼的有限的字元集。例如中文「上海」會被編碼為「fhqz97e」。
![]() | 此條目可參照英語維基百科相應條目來擴充。 (2016年12月) |
國際化域名編碼的目的是在於國際化域名標籤(IDNA)的框架中,使這些(多語言)的域名可以編碼為ASCII。編碼語法在文件 RFC 3492 中規定。
編碼過程
RFC 3492中說明:國際化域名編碼是一種稱為Bootstring的更普遍的演算法實例,它允許由部分基本的編碼集合組成的字串唯一表示由更大編碼集合組成的任何字串。配合統一碼文字的特性,國際化域名編碼定義了一般Bootstring演算法的參數。本節以德語字串"bücher"(書籍)為例,演示國際化域名編碼的編碼過程,該字串被編碼為"bcher-kva"。
首先,字串中的所有ASCII字元將被直接從輸入複製到輸出,任何其他字元將被跳過。例如,"bücher"被複製為 "bcher"。如果有任何字元被複製(即輸入中至少有一個ASCII字元),則在輸出中附加一個ASCII連字元(例如,"bücher"複製為"bcher-",其中"ü"不是ASCII字元,不發生複製)。
由於連字元本身是ASCII字元,因此可以出現在輸入中,並將被複製到輸出中。這並不會引起歧義,因為如果輸出包含連字元,被添加的連字元總是最後一個,這標誌著ASCII字元的結束。
對於輸入的非ASCII字元,依統一碼中碼位由低至高順序,編碼器會類比將非ASCII字元一一插入回去除非ASCII字元後的字串過程, 計算每個非ASCII字元對應的三個數字i、n和h:
- i 表示該非ASCII字元在輸入字串中的以0為開始索引的插入位置(類似於如C語言等的程式語言,用0來表示該非ASCII字元是輸入字串的第一個字元)。
- n 表示該非ASCII字元在統一碼中的碼位,減去127(127為最後一個ASCII字元)
- h 表示該非ASCII字元插入時可能有的插入位置。如"ü"要插入回"bcher"中,可能有"übcher"到"bcherü"6個位置可供插入。
編碼器隨後計算乘法n*h+i並將得到的數字編碼為一串36進制的可變長度數字,將這些數字轉化為ASCII碼,並將結果附加到輸出字串後。 每次計算後,該非ASCII字元會插入回去除非ASCII字元後的字串,因此h會增加1。 並且在計算下一個非ASCII字元的統一碼碼位時,該碼位需減去上一個非ASCII字元碼位。
編碼方式為:0 -> 'a', ..., 25 -> 'z', 26 -> '0', ..., 35 -> '9', 數字的數字按小端序排列。
此處的36進制的編碼並非通常意義下的下36進制整數,而是一種可變長度的整數。每個數字的最重要(most significant)的位(例如數字 "123 "中的 "1")在沒有上下文的情況下是可以辨識的。因此,多個數字可以無需分隔地連接,不會影響原始數字的辨識和提取。但此處每位數字進位的門檻閥值不同,並非每位皆是36進位。
為了防止非國際域名中的連字元被國際化域名編碼解碼,會在在國際化域名中的國際化域名編碼序列前加上字串xn--
。這被稱為ACE(ASCII Compatible Encoding)。[2]
因此,域名"bücher.tld"將會以ASCII形式表示為"xn--bcher-kva.tld"。
解碼器是具有兩個狀態變數i和n的有限狀態機。
i是字串的索引,範圍從0(代表可能插入的開始)到擴充字串的當前長度(代表可能插入的結束)。i從0開始。
n從128開始(128表示第一個非ASCII的碼位)。
狀態遞增是一個單調函式。一個狀態轉移要麼增加i,如果i達到最大,就重設i為零並增加n。下一個狀態轉移時,繼續增加i。 在每個狀態下,由n表示的碼位要麼被插入,要麼不被插入。
編碼器生成的數字代表在插入之前要跳過多少可能的結果。
在字串 "bcher "中,有六個位置可以插入一個字元(包括第一個字元前和最後一個字元後)。在最後一個ASCII碼位(127)和 "ü"(252,參見拉丁字母補充-1)之間有124個碼位。有一個 "ü "的插入位置必須跳過(位置0,即在'b'之前)。
因此,在到達正確位置前,解碼器將跳過共(6×124)+1=745個可能的插入位置。在該字元插入後,將有七個可能的地方插入下一個字元。
Remove ads
國際化域名編碼使用通用變長整數來表示這些值。例如,"kva "將用來表示碼號745。
小端序的數字系統允許不需要單獨的分隔符的變長編碼:低於閾值的數字標誌著它是最重要的數字,即是數字的結束。為了提高效率,閾值取決於數字的位置和以前的插入。同時,數字的權重也會變化。
在使用36個符號的數字系統中,不區分大小寫的'a'-'z'表示十進制數字0-25,'0'到'9'表示十進制數字26-35。因此,"kva",表示十進制數字序列"10 21 0"。
為了解碼這串符號,需要閾值序列。本例中,閾值序列為(1,1,26,26,...)。[3]最不重要的數字(least-significant digit)的權重(或位置值)總是1,具有權重1的'k'等於10(1×10=10)。下一個數字的權重取決於第一個閾值:一般來說,對於任意n,第n+1個數字的權重是第n個數字的權重乘以(36-第n個數字的閾值)。所以第二個符號的權重是36減去前一個閾值,即為35(36-1=35)。因此,前兩個符號'k'和'v'之和為10×1+21×35。由於第二個符號不小於其閾值1,因此還有更多符號。然而,由於本例中第三個符號是'a'(a=0),可以忽略其權重的計算。因此,"kva "代表十進制數字(10×1)+(21×35)=745。閾值本身由一個演算法為每個編碼字元序列決定,使其保持在1和26之間(包括1和26)。[4]字元的大小寫可以用來提供關於原始字串的大小寫資訊。[5]由於特殊字元按法編碼算的碼位排序,在插入"bücher"中特殊字元"ü"時,第一種可能是編碼為 "bcher-kvaa "的 "büücher",第二種可能是編碼為 "bcher-kvab "的 "bücüher",等等等等。在編碼為 "bcher-kvae "的 "bücherü "之後是代表插入ý的編碼,即ü之後的統一碼字元,從編碼為 "bcher-kvaf "的 "ýbücher "開始(與編碼為 "bcher-jvab "的 "übücher "不同),等等。
為了使編碼、解碼演算法簡單,編碼時並沒有試圖阻止一些編碼不允許的統一碼值:然而,解碼時應該檢查這些值。
國際化域名編碼的設計使其成可以在所有指令碼中工作,並通過在操作過程中嘗試適應字串中的字元集範圍進行自我最佳化。它針對字串由包含0個或更多ASCII字元和來自其他指令碼系統的字元組成的情況進行了最佳化,同時也能處理任意的統一碼字串。在使用DNS時需要注意,域名字串被認為已經使用nameprep進行了規格化處理,並且頂級域名在被國際化域名編碼之前被假設已經根據官方註冊的語言表進行了處理。同時,DNS協定對輸出國際化域名編碼字串的可接受長度也有所限制。
Remove ads
例子
下表展示了不同類型輸入的國際化域名編碼的例子。[6]
Remove ads
參考文獻
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads