在.NET中正確的計算出字串的長度

網際網路時至今日,早已經是一個地球村的概念,所有的資訊透過網際網路飛快的傳遞,讓語言的使用率與能見度都達到前所未有的境界,以目前來說全世界大概是對UTF-8編碼有共識,絕大部分的網站都是採用UTF-8編碼,而.NET內建的文字編碼是UTF-16,也就是說所有的文字在處理的過程中,都會以UTF-16來識別處理。

字串長度(文字長度)的基本計算 / String.Length

有些時刻我們必須針對字串進行長度計算,通常用於報表或是填補字串 Pad上,錯誤的字元數量計算可能會造成錯誤的結果,而偏偏進入到Unicode時代後,中文字的編碼是以一種變動的型態來進行編碼,有些常用的中文字元落在BMP(Basic Multilingual Plane),那麼就可以被正確的計算成一個字,例如:UTF-16編碼0x5F35。而有些罕見自可能會若在SIP(Supplementary Ideographic Plane),那麼這時候C#採用String.Length計算就會出錯,被計算成兩個字元。例如:𡩋UTF-16編碼0xD846 0xDE4B

字串長度(文字長度)的仔細計算

可以使用.NET的System.Globalization.StringInfo類別來輔助,程式碼如下:

string cDemo = "張鈞𡩋";
Console.WriteLine($"錯誤的長度:{cDemo.Length}");

var oSI = new System.Globalization.StringInfo(cDemo);
Console.WriteLine($"正確的長度:{oSI.LengthInTextElements}");

輸出的結果:

錯誤的長度:4 //𡩋的長度算錯了
正確的長度:3

透過上面的方法,可以更精準的計算出中文字正確的長度,就算是中英文混雜也適用。但倘落涉及到使用到菲茨派屈克修飾符(EMOJI MODIFIER FITZPATRICK)的Emojis,那麼計算就可能又變得不正確了。不過這個問題還好,畢竟沒有人會用Emojis當作名字吧?(好啦,或許未來有可能)

string cDemo = "🍖🧒🏿";
Console.WriteLine($"錯誤的長度:{cDemo.Length}");

var oSI = new System.Globalization.StringInfo(cDemo);
Console.WriteLine($"正確的長度:{oSI.LengthInTextElements}");

輸出的結果:

錯誤的長度:6
正確的長度:3

從上面的輸出結果發現很顯然是錯誤的,正確的長度應該是2才對。🍖其實有被正確的計算成1。但是🧒🏿因為涉及到修飾符,所以計算就錯誤了,被錯誤的計算成2

相關參考

.NET .NetFramework .NetCore string length count CJK emojis