代理區介紹
代理區(Surrogate)是基本多文種平面(Basic Multilingual Plane)中的一塊保留區域,Unicode碼範圍為0xD800-0xDFFF,這個範圍內的Unicode碼約定了不會對應任何的字元。
其中又將0xD800-0xDBFF用於高代理,將0xDC00-0xDFFF用於低代理。代理區的Unicode碼只有utf-16編碼才會用到。
4位元組codePoint
後面擴充的Unicode,0x10000-0x10FFFF都是超過2個位元組,要4個位元組來表示的。
a) c#中的char是2個位元組,遇到4位元組的Unicode碼是怎麼處理的?
用2個char表示一個字元,比如:"駼"的Unicode碼為0x2CCFF
string str = "A駼"; byte[] bytes = Encoding.Unicode.GetBytes(str); Console.WriteLine($"{str.Length}, {bytes.Length}"); //3, 6
上面的程式碼執行,得到的結果是這個字串有3個char(A佔1個char,駼佔2個char),6個位元組(A的Unicode碼為2位元組,駼的Unicode碼為4位元組)。
b) 字串含有2個char的字元時,如何獲取正確的字元數?
string str = "A駼"; int charCnt = 0; for (int i = 0; i < str.Length; ++i) { char c = str[i]; if (char.IsHighSurrogate(c)) { char lowSurrogateChar = str[++i]; int codePoint = char.ConvertToUtf32(c, lowSurrogateChar); string ch2 = char.ConvertFromUtf32(codePoint); Console.WriteLine($"0x{Convert.ToString(c, 16)}, 0x{Convert.ToString(lowSurrogateChar, 16)}"); } ++charCnt; } Console.WriteLine(charCnt);
代理Unicode碼與4位元組Unicode碼的轉換
4位元組Unicode碼 -> 代理Unicode碼
static void GetSurrogate(int codePoint, out char highSurrogate, out char lowSurrogate) { int temp = codePoint - 0x10000; highSurrogate = (char)((temp >> 10) + 0xD800); // 高代理(High Surrogate)碼點 lowSurrogate = (char)((temp & 0x3ff) + 0xDC00); // 低代理(Low Surrogate)碼點 }
代理Unicode碼 -> 4位元組Unicode碼
static int MergeSurrogatePair(char highSurrogate, char lowSurrogate) { int codePoint = ((int)highSurrogate - 0xD800) << 10 | ((int)lowSurrogate - 0xDC00); codePoint += 0x10000; Console.WriteLine($"0x{Convert.ToString(codePoint, 16)}"); return codePoint; }
或者用c#內建的api
int codePoint = char.ConvertToUtf32(highSurrogate, lowSurrogate); Console.WriteLine($"0x{Convert.ToString(codePoint, 16)}");
參考
Unicode編碼詳解(四):UTF-16編碼-CSDN部落格
C# - char型別的一些介紹 - yangxu-pro - 部落格園 (cnblogs.com)
C# string轉unicode編碼串 - 啊循 - 部落格園 (cnblogs.com)
在C#中處理字元簇_c# 代理項對(0xd880,0xd)無效,高代理項字元必須始終與低代理項字元承兌成對-CSDN部落格
UTF-8 與 UTF-16編碼詳解-CSDN部落格