Nei*_*ski 19 c# string unicode char astral-plane
我有一个字符范围限制列表,我需要检查字符串,但char.NET中的类型是UTF-16,因此一些字符变为古怪(代理)对.因此,当枚举a中的所有char's时string,我没有获得32位Unicode代码点,并且某些与高值的比较失败.
我非常了解Unicode,如果有必要,我可以自己解析字节,但我正在寻找一个C#/ .NET Framework BCL解决方案.所以......
如何将a转换为32位Unicode代码点string的数组(int[])?
Dan*_*ker 19
你问的是代码点.在UTF-16(C#char)中,只有两种可能性:
因此,假设字符串有效,则返回给定字符串的代码点数组:
public static int[] ToCodePoints(string str)
{
if (str == null)
throw new ArgumentNullException("str");
var codePoints = new List<int>(str.Length);
for (int i = 0; i < str.Length; i++)
{
codePoints.Add(Char.ConvertToUtf32(str, i));
if (Char.IsHighSurrogate(str[i]))
i += 1;
}
return codePoints.ToArray();
}
Run Code Online (Sandbox Code Playgroud)
代理对 and a composed character ñ:
ToCodePoints("\U0001F300 El Ni\u006E\u0303o"); // El Niño
// { 0x1f300, 0x20, 0x45, 0x6c, 0x20, 0x4e, 0x69, 0x6e, 0x303, 0x6f } // E l N i n ?? o
Run Code Online (Sandbox Code Playgroud)
这是另一个例子.这两个代码点代表一个带有断音重音的第32个音符,两个代理对:
ToCodePoints("\U0001D162\U0001D181"); //
// { 0x1d162, 0x1d181 } // ?
Run Code Online (Sandbox Code Playgroud)
当C标准化时,它们被分解为一个符头,结合词干,组合旗帜和组合口音 - 断奏,所有代理对:
ToCodePoints("\U0001D162\U0001D181".Normalize()); //
// { 0x1d158, 0x1d165, 0x1d170, 0x1d181 } // ?
Run Code Online (Sandbox Code Playgroud)
请注意,leppie的解决方案不正确.问题是关于代码点,而不是文本元素.文本元素是代码点的组合,它们一起形成单个字素.例如,在上面的示例ñ中,字符串中的字符串由拉丁文小写字母表示,n后跟组合代字号??.Leppie的解决方案会丢弃任何无法归一化为单个代码点的组合字符.
这个答案是不正确的.请参阅@ Virtlink的答案,了解正确答案.
static int[] ExtractScalars(string s)
{
if (!s.IsNormalized())
{
s = s.Normalize();
}
List<int> chars = new List<int>((s.Length * 3) / 2);
var ee = StringInfo.GetTextElementEnumerator(s);
while (ee.MoveNext())
{
string e = ee.GetTextElement();
chars.Add(char.ConvertToUtf32(e, 0));
}
return chars.ToArray();
}
Run Code Online (Sandbox Code Playgroud)
注意:处理复合字符需要规范化.
| 归档时间: |
|
| 查看次数: |
3992 次 |
| 最近记录: |