我有一个需要提供规范化字符串的例程.但是,进入的数据不一定是干净的,如果字符串包含无效的代码点,String.Normalize()会引发ArgumentException.
我想做的只是用一个一次性字符替换那些代码点,例如'?'.但要做到这一点,我需要一种有效的方法来搜索字符串,以便首先找到它们.有什么好办法呢?
以下代码有效,但它基本上使用try/catch作为粗略的if语句,因此性能很糟糕.我只是分享它来说明我正在寻找的行为:
private static string ReplaceInvalidCodePoints(string aString, string replacement)
{
var builder = new StringBuilder(aString.Length);
var enumerator = StringInfo.GetTextElementEnumerator(aString);
while (enumerator.MoveNext())
{
string nextElement;
try { nextElement = enumerator.GetTextElement().Normalize(); }
catch (ArgumentException) { nextElement = replacement; }
builder.Append(nextElement);
}
return builder.ToString();
}
Run Code Online (Sandbox Code Playgroud)
(编辑:)我正在考虑将文本转换为UTF-32,以便我可以快速迭代它,看看每个dword是否对应一个有效的代码点.有没有这样做的功能?如果没有,是否有一个无效范围列表在那里漂浮?
似乎唯一的方法是"手动",就像你已经完成的那样.下面是给出了相同的结果你的一个版本,但是是快一点(约4倍于所有的字符串chars最多char.MaxValue,少改善达U+10FFFF)和不需要unsafe的代码.我还简化并评论了我的IsCharacter方法来解释每个选择:
static string ReplaceNonCharacters(string aString, char replacement)
{
var sb = new StringBuilder(aString.Length);
for (var i = 0; i < aString.Length; i++)
{
if (char.IsSurrogatePair(aString, i))
{
int c = char.ConvertToUtf32(aString, i);
i++;
if (IsCharacter(c))
sb.Append(char.ConvertFromUtf32(c));
else
sb.Append(replacement);
}
else
{
char c = aString[i];
if (IsCharacter(c))
sb.Append(c);
else
sb.Append(replacement);
}
}
return sb.ToString();
}
static bool IsCharacter(int point)
{
return point < 0xFDD0 || // everything below here is fine
point > 0xFDEF && // exclude the 0xFFD0...0xFDEF non-characters
(point & 0xfffE) != 0xFFFE; // exclude all other non-characters
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4126 次 |
| 最近记录: |