返回C#中的字符代码点

时间:2012-12-15 16:32:39

标签: c# unicode unicode-string

如何归还角色的Unicode Code Point?例如,如果输入为“A”,则输出应为“U + 0041”。理想情况下,解决方案应该处理surrogate pairs

使用代码点我指的是实际代码点according to Unicode,它与 code unit 不同(UTF8具有8位代码单元, UTF16具有16位代码单元,UTF32具有32位代码单元,在后一种情况下,该值等于代码点,在考虑到字节序后)。

7 个答案:

答案 0 :(得分:13)

以下代码将string输入的代码点写入控制台:

string input = "\uD834\uDD61";

for (var i = 0; i < input.Length; i += char.IsSurrogatePair(input, i) ? 2 : 1)
{
    var codepoint = char.ConvertToUtf32(input, i);

    Console.WriteLine("U+{0:X4}", codepoint);
}

输出:

U+1D161

由于.NET中的字符串是UTF-16编码的,因此构成字符串的char值需要先转换为UTF-32。

答案 1 :(得分:8)

很简单,因为C#中的字符实际上是UTF16代码点:

char x = 'A';
Console.WriteLine("U+{0:x4}", (int)x);

为了解决这些注释,C#中的char是一个16位数字,并保存一个UTF16代码点。位空间16以上的代码点不能用C#字符表示。 C#中的字符不是可变宽度。然而,字符串可以具有彼此跟随的2个字符,每个字符是代码单元,形成UTF16代码点。如果你有一个字符串输入和16位空格之上的字符,你可以使用char.IsSurrogatePairChar.ConvertToUtf32,如另一个答案所示:

string input = ....
for(int i = 0 ; i < input.Length ; i += Char.IsSurrogatePair(input,i) ? 2 : 1)
{
    int x = Char.ConvertToUtf32(input, i);
    Console.WriteLine("U+{0:X4}", x);
}

答案 2 :(得分:2)

实际上@Yogendra Singh的答案有一些优点,目前唯一一个负面投票的人。 这项工作可以像这样完成

    public static IEnumerable<int> Utf8ToCodePoints(this string s)
    {
        var utf32Bytes = Encoding.UTF32.GetBytes(s);
        var bytesPerCharInUtf32 = 4;
        Debug.Assert(utf32bytes.Length % bytesPerCharInUtf32 == 0);
        for (int i = 0; i < utf32bytes.Length; i+= bytesPerCharInUtf32)
        {
            yield return BitConverter.ToInt32(utf32bytes, i);
        }
    }

使用

进行测试
    var surrogatePairInput = "abc";
    Debug.Assert(surrogatePairInput.Length == 5);
    var pointsAsString = string.Join(";" , 
        surrogatePairInput
        .Utf8ToCodePoints()
        .Select(p => $"U+{p:X4}"));
    Debug.Assert(pointsAsString == "U+0061;U+0062;U+0063;U+1F4A9");

示例是相关的,因为poo堆被表示为代理对。

答案 3 :(得分:1)

C#无法在char中存储unicode代码点,因为char只有2个字节,而unicode代码点通常超过该长度。解决方案是将代码点表示为字节序列(作为字节数组或“展平”为32位原语)或字符串。接受的答案转换为UTF32,但这并不总是理想的。

这是我们用于将字符串拆分为其unicode代码点组件的代码,但保留了本机UTF-16编码。结果是一个可枚举的,可用于在C#/ .NET中本地比较(子)字符串:

    public class InvalidEncodingException : System.Exception
    { }

    public static IEnumerable<string> UnicodeCodepoints(this string s)
    {
        for (int i = 0; i < s.Length; ++i)
        {
            if (Char.IsSurrogate(s[i]))
            {
                if (s.Length < i + 2)
                {
                    throw new InvalidEncodingException();
                }
                yield return string.Format("{0}{1}", s[i], s[++i]);
            }
            else
            {
                yield return string.Format("{0}", s[i]);
            }
        }
    }
}

答案 4 :(得分:1)

在 .NET Core 3.0 或更高版本中,您可以使用 Rune Struct:

// Note that ? and ? are encoded using surrogate pairs
// but A, B, C and ✋ are not
var runes = "ABC✋??".EnumerateRunes();

foreach (var r in runes)
    Console.Write($"U+{r.Value:X4} ");
        
// Writes: U+0041 U+0042 U+0043 U+270B U+1F609 U+1F44D

答案 5 :(得分:-1)

public static string ToCodePointNotation(char c)
{

    return "U+" + ((int)c).ToString("X4");
}

Console.WriteLine(ToCodePointNotation('a')); //U+0061

答案 6 :(得分:-2)

我在msdn forum找到了一个小方法。希望这会有所帮助。

    public int get_char_code(char character){ 
        UTF32Encoding encoding = new UTF32Encoding(); 
        byte[] bytes = encoding.GetBytes(character.ToString().ToCharArray()); 
        return BitConverter.ToInt32(bytes, 0); 
    }