Unicode編碼 - 代理區和4位元組codePoint

yanghui01發表於2024-09-12

代理區介紹

代理區(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部落格

相關文章