.NET字符串对象和无效的Unicode代码点

.NET字符串对象和无效的Unicode代码点,.net,string,unicode,.net,String,Unicode,.NET字符串对象是否可能包含无效的Unicode代码点 如果是,这是如何发生的(我如何确定字符串是否有这样的无效字符)?我认为只有当有人将单个元素设置为hi或lo代理时,.NET字符串中的无效代码点才会发生。也可能有人从有效的代理项对中删除hi或lo代理项,后者不仅可以通过删除元素,还可以通过更改元素的值来实现。在我看来,答案是“是”,这是可能发生的,唯一的原因可能是字符串中存在孤立的hi或lo代理。你有一个真正的例子字符串吗?把它贴在这里,我就可以检查出什么问题了 B.t.w.UTF-16文

.NET字符串对象是否可能包含无效的Unicode代码点


如果是,这是如何发生的(我如何确定字符串是否有这样的无效字符)?

我认为只有当有人将单个元素设置为hi或lo代理时,.NET字符串中的无效代码点才会发生。也可能有人从有效的代理项对中删除hi或lo代理项,后者不仅可以通过删除元素,还可以通过更改元素的值来实现。在我看来,答案是“是”,这是可能发生的,唯一的原因可能是字符串中存在孤立的hi或lo代理。你有一个真正的例子字符串吗?把它贴在这里,我就可以检查出什么问题了

B.t.w.UTF-16文件也是如此。这是可能发生的。对于具有0xFFEE BOM的utf-16LE文件,请确保您的第一个字符不是0,因为您的前4个字节是0xFFFE0000,这肯定会被解释为utf-32LE BOM而不是utf-16LE BOM

使用UTF-16对.NET和C#中的所有字符串进行编码,但有一个例外(取自):

…有两种不同的表示法:大多数情况下,UTF-16 已使用,但属性构造函数参数使用UTF-8


是的,这是可能的。根据微软的文档,一个.NET只是

字符串对象是表示字符串的System.Char对象的顺序集合

而.NET

将字符表示为UTF-16代码单元

综上所述,这意味着一个.NET字符串只是一个UTF-16代码单元序列,无论它们是否是符合Unicode标准的有效字符串。有很多方法可以实现这一点,我能想到的一些更常见的方法是:

  • 一个非UTF-16字节的流在没有正确转换的情况下被错误地放入字符串对象
  • 字符串对象在代理项对之间拆分
  • 有人故意加入这样一个字符串来测试系统的健壮性
因此,以下C#代码完全合法,并将编译:

类测试
静态void Main(){
字符串s=
“\uEEEE”+//一个专用字符
“\uDDDD”+//未配对的代理项字符
“\uFFFF”+//一个Unicode非字符
“\u0888”;//当前未分配的字符
System.Console.WriteLine;//输出高度依赖于控制台
}
}

虽然@DPenner给出的响应非常好(我把它作为一个起点),但我想给出一些其他细节。 除了我认为是无效字符串的明显标志的孤立代理之外,字符串总是可能包含未分配的代码点,并且这种情况不能被.NET Framework视为错误,因为新字符总是添加到Unicode标准中,例如,请参见Unicode版本。而且,为了让事情更清楚,这个调用
Char.getUnicodeCegory(Char.ConvertFromUtf32(0x1F01C),0)返回
UnicodeCategory.OtherNotAssigned
,但当使用.NET 4.0时,它将返回
UnicodeCategory.OtherSymbol

除此之外,还有另一个有趣的问题:即使是.NET类库方法也不同意如何处理Unicode非字符和未配对的代理字符。例如:

  • 未配对代理字符
    • System.Text.Encoding.Unicode.GetBytes(“\uDDDD”)
      -返回的编码是无效的,即数据被认为无效
    • “\uDDDD.Normalize()-引发异常,消息为“在索引0处找到无效的Unicode代码点”。也就是说,数据被视为无效
  • 非字符代码点
    • System.Text.Encoding.Unicode.GetBytes(“\uFFFF”)
      -返回
      {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;
}
//
///搜索字符串中的无效字符(Unicode标准中定义的非字符和无效代理项对)
/// 
///用于搜索无效字符的字符串
///第一个坏字符的索引,如果未找到坏字符,则为-1
静态int FindInvalidCharIndex(字符串aString)
{
int-ch;
int chlow;
for(int i=0;i=0xD800&&ch检查代理项对
i++;
if(i==aString.Length)
{
//最后一个字符是高代理项,因此它缺少一对
返回i-1;
}
chlow=aString[i];
如果(!(chlow>=0xDC00&&chlow 0x10FFFF)
{
//无效的Unicode代码点-最大值
返回i;
}
如果((ch&0xFFFE)=0xFFFE)
{
//找到其他非字符
返回i;
}
//找到了一对好的代理
继续;
}

如果(通常情况下,ch>=0xDC00&&ch=0xFDD0&&ch坏的pinvoke。避免问XY问题。@HansPassant我不能只发布我的第一个问题。对太短的问题有某种验证,所以我还添加了第二部分,我认为这是相关的。@HansPassant:那么,没有不以错误的方式原生的不匹配代理吗?什么关于未分配的代码点?不,我没有样本,但如果可能的话,我想看一个。我有这样的文件,但我怎么能上传到这里?我离开了