String StartsWith 方法在任何情况下都为字节顺序标记返回 true [duplicate]

String StartsWith method returns true for byte order mark in any case [duplicate]

提问人:username 提问时间:6/20/2023 更新时间:6/20/2023 访问量:39

问:

我盲目地复制了其中一个 stackoverflow 答案,但它并没有像我预期的那样对我有用。 我需要从字符串中删除一个 UTF8 字节顺序标记,不知何故,inputText.StartsWith(byteOrderMark) 总是为任何字符串返回 true:

internal class Program
{
    static void Main(string[] args)
    {
        var inputText = "hello";
        string byteOrderMark = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
        if (inputText.StartsWith(byteOrderMark))
            inputText = inputText.Remove(0, byteOrderMark.Length);
        Console.WriteLine(inputText); // ello
        Console.WriteLine(inputText[0] == byteOrderMark[0]); // false
    }
}

我可以逐个字符检查它,没有问题。我很感兴趣为什么即使字符串不以 UTF8 前导码开头,StartsWith 也会返回 true?

C# 字符串 UTF-8 开始使用

评论

0赞 ProgrammingLlama 6/20/2023
可能和这个这个一样。
0赞 dbc 6/20/2023
那是什么答案?也许我们应该修复它。
1赞 dbc 6/20/2023
@ProgrammingLlama - 也许是这个?与TrueWill的这个实际上是正确的相比,错误的答案在“趋势”类别中排在第一位。
2赞 dbc 6/20/2023
@username - 这不是一个糟糕的副本,因为标题非常清楚。
2赞 ProgrammingLlama 6/20/2023
@username 像这样的重复项可以作为其他人寻找相同或类似问题解决方案的路标,我认为您的问题将来应该出现在其他人的搜索中,所以离开它并不是一个坏主意。

答:

2赞 dbc 6/20/2023 #1

您需要使用:StringComparison.Ordinal

if (inputText.StartsWith(byteOrderMark, StringComparison.Ordinal))
    inputText = inputText.Remove(0, byteOrderMark.Length);

文档中所述:String.StartsWith(String)

此方法使用当前区域性执行单词(区分大小写和区分区域性)比较。

由于 BOM 是非打印的,显然在你的区域性中,你的调用等同于 ,这始终是正确的。inputText.StartsWith(string.Empty)

文档进一步指出:

如使用字符串的最佳实践中所述,建议避免调用替换默认值的字符串比较方法,而应调用需要显式指定参数的方法。若要使用当前区域性的字符串比较规则确定字符串是否以特定子字符串开头,请通过调用 StartsWith(String, StringComparison) 方法重载(其值为 CurrentCulture)作为其 comparisonType 参数来显式指示你的意图。

看来你可能被这个咬了。