陈斌彬的技术博客

Stay foolish,stay hungry

枚举字符串并考虑Unicode Surrogate(转)

转:https://www.mgenware.com/blog/?p=2202

.NET中字符串类型的Unicode的编码是UTF16,所以foreach枚举字符串可能会枚举到两个Unicode Surrogate值。为了枚举字符串中每个完整的Unicode字符值,写个小方法。很简单,通过Char.IsSurrogate判断是否是Unicode Surrogate,然后通过Char.ConvertToUtf32方法把两个Surrogate值转换成一个完整的int代表完整的Unicode编码值。

如下代码:

static IEnumerable<int> EnumerateCharValues(string str)
{
    int i = 0;
    while (i < str.Length)
    {
        var c = str[i];
        if (Char.IsSurrogate(c) && i != str.Length - 1)
        {
            i += 2;
            yield return Char.ConvertToUtf32(c, str[i - 1]);
        }
        else
        {
            i++;
            yield return c;
        }
    }
}

测试:

//创建一对Surrogate
var surrogatePair = Char.ConvertFromUtf32(0x1F600);
//构造一个测试字符串
var str = "a" + surrogatePair + "b" + surrogatePair;

Console.WriteLine("Length: {0}", str.Length);
foreach (var i in EnumerateCharValues(str))
    Console.WriteLine("U+{0:X}", i);

输出:

Length: 6
U+61
U+1F600
U+62
U+1F600

OK,虽然String长度为6,但是因为有2对Surrogate,所以总共只有4个字符。