Nit*_*amk 13 c# string unicode .net-4.5
编辑:我原本以为这与.NET Framework 4.5有关.原来它也适用于.NET Framework 4.0.
Windows Server 2012中的字符串处理方式发生了变化,我试图更好地理解它.似乎StartsWith的行为已经改变.使用.NET Framework 4.0和4.5可以重现该问题.
使用Windows 7上的.NET Framework 4.5,下面的程序打印"False,t".在Windows 2012 Server上,它会打印"True,t".
internal class Program
{
private static void Main(string[] args)
{
string byteOrderMark = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
Console.WriteLine("test".StartsWith(byteOrderMark));
Console.WriteLine("test"[0]);
}
}
Run Code Online (Sandbox Code Playgroud)
换句话说,无论字符串内容如何,StartsWith(ByteOrderMark)都返回true.如果您有使用以下方法尝试剥离字节顺序标记的代码,此代码将在Windows 7上正常工作,但将在Windows 2012上打印"est".
internal class Program
{
private static void Main(string[] args)
{
string byteOrderMark = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
string someString = "Test";
if (someString.StartsWith(byteOrderMark))
someString = someString.Substring(1);
Console.WriteLine("{0}", someString);
Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)
}
我意识到如果你在字符串中有字节顺序标记,你已经做错了,但我们正在与具有此功能的遗留代码集成.我知道我可以通过以下方式解决这个具体问题,但我想更好地理解这个问题.
someString = someString.Trim(byteOrderMark[0]);
Run Code Online (Sandbox Code Playgroud)
Hans Passsant建议使用UTF8Encoding的构造函数,它允许我明确地告诉它发出UTF8标识符.我尝试了这个,但它给出了相同的结果.以下代码在Windows 7和Windows Server 2012之间的输出方面有所不同.在Windows 7上,它打印"Result:False".在Windows Server 2012上,它打印"Result:True".
private static void Main(string[] args)
{
var encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: true);
string byteOrderMark = encoding.GetString(encoding.GetPreamble());
Console.WriteLine("Result: " + "Hello".StartsWith(byteOrderMark));
Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)
我还尝试了以下变体,它在Windows 7上打印False,False,False但在Windows Server 2012上打印为True,True,False,这证实它与Windows Server 2012上StartsWith的实现有关.
private static void Main(string[] args)
{
var encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: true);
string byteOrderMark = encoding.GetString(encoding.GetPreamble());
Console.WriteLine("Hello".StartsWith(byteOrderMark));
Console.WriteLine("Hello".StartsWith('\ufeff'.ToString()));
Console.WriteLine("Hello"[0] == '\ufeff');
Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)
Han*_*ant 13
原来我可以重复这一点,在Windows 8.1上运行测试程序.它与Server 2012属于同一个"家庭".
最可能的问题来源是文化敏感的比较规则已经改变.它们可能是,呃,片状,并且可能在这些角色上有奇怪的结果.BOM是零宽度空间.推理这个需要与理解为什么"abc"同样的心理体操.StartsWith("")返回true :)
您需要使用StringComparison.Ordinal解决您的问题.这产生了假,假,假:
private static void Main(string[] args) {
var encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: true);
string byteOrderMark = encoding.GetString(encoding.GetPreamble());
Console.WriteLine("Hello".StartsWith(byteOrderMark, StringComparison.Ordinal));
Console.WriteLine("Hello".StartsWith("\ufeff", StringComparison.Ordinal));
Console.WriteLine("Hello"[0] == '\ufeff');
Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)