Windows Server 2012 中的 StartsWith 更改 [英] StartsWith change in Windows Server 2012

查看:25
本文介绍了Windows Server 2012 中的 StartsWith 更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最初认为这与 .NET Framework 4.5 有关.结果证明它也适用于 .NET Framework 4.0.

I originally thought this was related to .NET Framework 4.5. Turned out it applies to .NET Framework 4.0 as well.

Windows Server 2012 中处理字符串的方式发生了变化,我正试图更好地理解这一点.StartsWith 的行为似乎发生了变化.使用 .NET Framework 4.0 和 4.5 都可以重现该问题.

There's a change in how strings are handled in Windows Server 2012 which I'm trying to understand better. It seems like the behavior of StartsWith has changed. The issue is reproducible using both .NET Framework 4.0 and 4.5.

在 Windows 7 上使用 .NET Framework 4.5,下面的程序打印False, t".在 Windows 2012 Server 上,它会打印True, t".

With .NET Framework 4.5 on Windows 7, the program below prints "False, t". On Windows 2012 Server, it prints "True, t" instead.

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]);
   }
}

换句话说,无论字符串内容如何,​​StartsWith(ByteOrderMark) 都返回 true.如果您的代码尝试使用以下方法去除字节顺序标记,则此代码在 Windows 7 上可以正常工作,但在 Windows 2012 上会打印est".

In other words, StartsWith(ByteOrderMark) returns true regardless of string content. If you have code which attempts to strip away the byte order mark using the following method, this code will work fine with on Windows 7 but will print "est" on Windows 2012.

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();

  }

}

我意识到如果字符串中有字节顺序标记,您就已经做错了,但我们正在与具有此功能的遗留代码集成.我知道我可以通过执行以下操作来解决此特定问题,但我想更好地了解该问题.

I realize that you have already done something wrong if you have byte order markers in a string, but we're integrating with legacy code which has this. I know I can solve this specific issue by doing something like below, but I want to understand the problem better.

someString = someString.Trim(byteOrderMark[0]);

Hans Passsant 建议使用 UTF8Encoding 的构造函数,它让我明确地告诉它发出 UTF8 标识符.我试过这个,但它给出了相同的结果.下面的代码在 Windows 7 和 Windows Server 2012 之间的输出不同.在 Windows 7 上,它打印结果:假".在 Windows Server 2012 上,它会打印Result: True".

Hans Passsant suggested using the constructor of UTF8Encoding which lets me tell it explicitly to emit UTF8 identifier. I tried this, but it gives the same result. The below code differs in output between Windows 7 and Windows Server 2012. On Windows 7, it prints "Result: False". On Windows Server 2012 it prints "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();
  }

我还尝试了以下变体,它在 Windows 7 上打印 False, False, False 但在 Windows Server 2012 上打印 True, True, False,这证实它与 Windows Server 2012 上的 StartsWith 实现有关.

I've also tried the following variant, which prints False, False, False on Windows 7 but True, True, False on Windows Server 2012, which confirms it's related to the implementation of StartsWith on Windows Server 2012.

  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();
  }

推荐答案

结果证明我可以重现这个,在 Windows 8.1 上运行测试程序.它与 Server 2012 属于同一个家族".

Turns out I could repro this, running the test program on Windows 8.1. It is in the same "family" as Server 2012.

问题的最可能来源是文化敏感的比较规则已更改.它们可能是,呃,片状,并且可能会对这些类型的角色产生奇怪的结果.BOM 是一个零宽度空间.推理出这一点需要与理解为什么 "abc".StartsWith("") 返回 true 相同的心理体操:)

The most likely source of the problem is that the culture sensitive comparison rules have changed. They can be, erm, flaky and can have odd outcomes on these kind of characters. The BOM is a zero-width space. Reasoning this out requires the same kind of mental gymnastics as understanding why "abc".StartsWith("") returns true :)

您需要使用 StringComparison.Ordinal 来解决您的问题.这产生了假,假,假:

You need to solve your problem by using StringComparison.Ordinal. This produced False, False, False:

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();
}

这篇关于Windows Server 2012 中的 StartsWith 更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆