簡體   English   中英

如何從 UTF-16 字符串中確定 Unicode 字符?

[英]How to Determine Unicode Characters from a UTF-16 String?

我的字符串包含一個奇怪的 Unicode 空格字符,但我不確定那是什么字符。 我知道在 C# 中,內存中的字符串使用 UTF-16 格式進行編碼。 確定哪些 Unicode 字符組成字符串的好方法是什么?

這個問題被標記為可能重復以在 C# 中確定字符串的編碼這不是這個問題的重復,因為我不是在問編碼是什么。 我已經知道 C# 中的字符串被編碼為 UTF-16。 我只是要求一種簡單的方法來確定字符串中的 Unicode 值。

BMP 字符的長度最多為 2 個字節(值 0x0000-0xffff),因此有很好的覆蓋范圍。 中文、泰文、甚至蒙古字母的字符都在那里,所以如果你不是編碼專家,如果你的代碼只處理 BMP 字符,你可能會被原諒。 但同樣如此,像http://www.fileformat.info/info/unicode/char/10330/index.htm這樣的字符不會被假設它適合兩個字節的代碼正確處理。

Unicode 似乎將字符識別為數字代碼點。 然而,並非所有代碼點實際上都指代字符,因為 Unicode 具有組合字符的概念(我對此知之甚少)。 然而,每個 Unicode 字符串,即使是一些無效的字符串(例如,非法的組合字符序列),都可以被認為是一個代碼點(數字)列表。

在 UTF-16 編碼中,每個代碼點都被編碼為 2 或 4 字節序列。 在 .net 中, Char可能大致對應於 2 字節 UTF-16 序列或 4 字節 UTF-16 序列的一半。 Char包含一個 4 字節序列的一半時,它被認為是“代理”,因為它只有在與另一個必須保持在一起的Char組合時才有意義。 要開始檢查您的 .net 字符串,您可以讓 .net 告訴您字符串中包含的代碼點,並在必要時自動將代理對組合在一起。 .net 提供Char.ConvertToUtf32其描述如下:

將字符串中指定位置的 UTF-16 編碼字符或代理項對的值轉換為 Unicode 代碼點。

Char.ConvertToUtf32(String s, Int32 index)文檔指出,以下情況會引發ArgumentException

指定的索引位置包含代理對,並且該對中的第一個字符不是有效的高代理,或者該對中的第二個字符不是有效的低代理。

因此,您可以在字符串中逐個字符地查找所有 Unicode 代碼點,並借助Char.IsHighSurrogate()Char.ConvertToUtf32() 當您沒有遇到高代理時,當前字符適合一個Char ,您只需要在字符串中前進一個Char 如果您確實遇到了高位代理,則該角色需要兩個Char並且您需要前進兩個:

static IEnumerable<int> GetCodePoints(string s)
{
    for (var i = 0; i < s.Length; i += char.IsHighSurrogate(s[i]) ? 2 : 1)
    {
        yield return char.ConvertToUtf32(s, i);
    }
}

當您說“來自 UTF-16 字符串”時,這可能意味着您已讀入一系列格式化為 UTF-16 的字節。 如果是這種情況,您需要在傳遞給上述方法之前將其轉換為 .net 字符串:

GetCodePoints(Encoding.UTF16.GetString(myUtf16Blob));

另一個注意事項:根據您構建String實例的方式,它可能包含關於代理對的非法Char序列。 對於這樣的字符串, Char.ConvertToUtf32()在遇到時會拋出異常。 但是,我認為Encoding.GetString()將始終返回有效字符串或引發異常。 因此,通常,只要您的String實例來自“好”來源,您就不必擔心Char.ConvertToUtf32()拋出(除非您為索引偏移量傳入隨機值,因為您的偏移量可能位於代理對)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM