And*_*tan 4 .net string unicode
.NET String对象是否可能包含无效的Unicode代码点?
如果是,可能会发生这种情况(如何确定字符串是否具有此类无效字符)?
对的,这是可能的.根据微软的文档,.NET String很简单
String对象是表示字符串的System.Char对象的顺序集合.
而.NET Char
将字符表示为UTF-16代码单元.
总之,这意味着.NET String只是一系列UTF-16代码单元,无论它们是否是根据Unicode标准的有效字符串.有很多方法可以实现,我能想到的一些更常见的方法是:
因此,以下C#代码是完全合法的并将编译:
class Test
static void Main(){
string s =
"\uEEEE" + // A private use character
"\uDDDD" + // An unpaired surrogate character
"\uFFFF" + // A Unicode noncharacter
"\u0888"; // A currently unassigned character
System.Console.WriteLine(s); // Output is highly console dependent
}
}
Run Code Online (Sandbox Code Playgroud)
尽管@DPenner给出的响应非常好(并且我以它为起点),但我想提供一些其他细节。除了我认为是无效字符串的明显标志的孤立代理之外,字符串始终包含未分配的代码点的可能性,并且.NET Framework不能将这种情况视为错误,因为新字符总是添加到Unicode标准中,例如参见Unicode版本http://en.wikipedia.org/wiki/Unicode#Versions。并且,为了使情况更清楚,使用.NET 2.0时此调用Char.GetUnicodeCategory(Char.ConvertFromUtf32(0x1F01C), 0);返回 UnicodeCategory.OtherNotAssigned,但是UnicodeCategory.OtherSymbol使用.NET 4.0时将返回。
除此之外,还有一个有趣的观点:.NET类库方法甚至都没有就如何处理Unicode非字符和未配对的代理字符达成共识。例如:
System.Text.Encoding.Unicode.GetBytes("\uDDDD");-返回替换字符{ 0xfd, 0xff}的编码,即数据被视为无效。"\uDDDD".Normalize(); -引发异常,并显示消息“在索引0找到无效的Unicode代码点”,即,该数据被视为无效。System.Text.Encoding.Unicode.GetBytes("\uFFFF");-return {0xff, 0xff},即数据被认为是有效的。"\uFFFF".Normalize(); -引发异常,并显示消息“在索引0找到无效的Unicode代码点”,即该数据被视为无效。下面是一种在字符串中搜索无效字符的方法:
/// <summary>
/// Searches invalid charachters (non-chars defined in Unicode standard and invalid surrogate pairs) in a string
/// </summary>
/// <param name="aString"> the string to search for invalid chars </param>
/// <returns>the index of the first bad char or -1 if no bad char is found</returns>
static int FindInvalidCharIndex(string aString)
{
int ch;
int chlow;
for (int i = 0; i < aString.Length; i++)
{
ch = aString[i];
if (ch < 0xD800) // char is up to first high surrogate
{
continue;
}
if (ch >= 0xD800 && ch <= 0xDBFF)
{
// found high surrogate -> check surrogate pair
i++;
if (i == aString.Length)
{
// last char is high surrogate, so it is missing its pair
return i - 1;
}
chlow = aString[i];
if (!(chlow >= 0xDC00 && chlow <= 0xDFFF))
{
// did not found a low surrogate after the high surrogate
return i - 1;
}
// convert to UTF32 - like in Char.ConvertToUtf32(highSurrogate, lowSurrogate)
ch = (ch - 0xD800) * 0x400 + (chlow - 0xDC00) + 0x10000;
if (ch > 0x10FFFF)
{
// invalid Unicode code point - maximum excedeed
return i;
}
if ((ch & 0xFFFE) == 0xFFFE)
{
// other non-char found
return i;
}
// found a good surrogate pair
continue;
}
if (ch >= 0xDC00 && ch <= 0xDFFF)
{
// unexpected low surrogate
return i;
}
if (ch >= 0xFDD0 && ch <= 0xFDEF)
{
// non-chars are considered invalid by System.Text.Encoding.GetBytes() and String.Normalize()
return i;
}
if ((ch & 0xFFFE) == 0xFFFE)
{
// other non-char found
return i;
}
}
return -1;
}
Run Code Online (Sandbox Code Playgroud)