最近在處理一些中文字的問題時,發現一個已經用了兩年多的程式,碰到一些特別罕見的中文字就無法正確執行。當初寫這個程式時,只有測試一般的 Unicode 字元,而沒有考慮到那些特別罕見的中文字。試看這個例子:
string str = "風";
char ch = s[0];
MessageBox.Show(ch.ToString());
不意外,畫面顯示的結果是 "風"。如果用 str.Length 來取字串長度,得到的結果也是預料中的 1。
對於一般常見或「稍微罕見」的中文字,上面的寫法並不會有問題。但如果碰到特別罕見的中文字就會出狀況了,例如這個:
string str = "𩗴";
char ch = str[0];
MessageBox.Show(ch.ToString());
輸出的結果是.....亂碼。
由於 Unicode 的總字數超過 65536 個字元,有些罕見字的編碼會超過 2 bytes,例如此例的「𩗴」(讀作四聲「ㄅㄥˋ」),這個字的編碼佔 4 bytes,若使用 str[0] 的方式取出第一個字元,就會只抓到整個 Unicode 字元的一半,因而出現亂碼--姑且叫它亂碼 1/2 :p (此例的 str.Length 是多少?)
有關 surrogate pairs 和 combining character sequences 的說明,這裡就偷懶跳過,寫程式時只需牢記:在 .NET 裡面,Unicode 字元必須以字串的方式處理。
因此,前面的範例應該改成這樣:
string str = "𩗴";
string ch = StringInfo.GetNextTextElement(str);
MessageBox.Show(ch);
StringInfo 類別隸屬 System.Globalization 命名空間,其 GetNextTextElement 方法可以傳回第一個 Unicode 字元(注意型別是 string),或傳回特定索引位置的字元。詳細用法請參考 MSDN 線上文件。
string str = "風";
char ch = s[0];
MessageBox.Show(ch.ToString());
不意外,畫面顯示的結果是 "風"。如果用 str.Length 來取字串長度,得到的結果也是預料中的 1。
對於一般常見或「稍微罕見」的中文字,上面的寫法並不會有問題。但如果碰到特別罕見的中文字就會出狀況了,例如這個:
string str = "𩗴";
char ch = str[0];
MessageBox.Show(ch.ToString());
輸出的結果是.....亂碼。
由於 Unicode 的總字數超過 65536 個字元,有些罕見字的編碼會超過 2 bytes,例如此例的「𩗴」(讀作四聲「ㄅㄥˋ」),這個字的編碼佔 4 bytes,若使用 str[0] 的方式取出第一個字元,就會只抓到整個 Unicode 字元的一半,因而出現亂碼--姑且叫它亂碼 1/2 :p (此例的 str.Length 是多少?)
有關 surrogate pairs 和 combining character sequences 的說明,這裡就偷懶跳過,寫程式時只需牢記:在 .NET 裡面,Unicode 字元必須以字串的方式處理。
因此,前面的範例應該改成這樣:
string str = "𩗴";
string ch = StringInfo.GetNextTextElement(str);
MessageBox.Show(ch);
StringInfo 類別隸屬 System.Globalization 命名空間,其 GetNextTextElement 方法可以傳回第一個 Unicode 字元(注意型別是 string),或傳回特定索引位置的字元。詳細用法請參考 MSDN 線上文件。
註:這篇的 "𩗴" 字,在網頁上輸入時,是寫成:𩗴這個數字可以經由呼叫 Char.ConvertToUtf32("𩗴") 得到。
阿阿...此例的 str.length 居然是 2.
回覆刪除叫我如何相信 str.length 呢 (淚)
呵...如果應用程式不太會碰到極罕見的漢字,倒是還 OK 啦。有些文字編輯器的軟體也無法正確處理這種雙字元組合成的罕見字。
回覆刪除