簡體   English   中英

Windows Server 2012 中的 StartsWith 更改

[英]StartsWith change in Windows Server 2012

編輯:我最初認為這與 .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]);
   }
}

換句話說,無論字符串內容如何,​​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();

  }

}

我意識到如果您在字符串中有字節順序標記,您已經做錯了,但我們正在與具有此功能的遺留代碼集成。 我知道我可以通過執行以下操作來解決這個特定問題,但我想更好地理解這個問題。

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

Hans Passsant 建議使用 UTF8Encoding 的構造函數,它讓我明確地告訴它發出 UTF8 標識符。 我試過這個,但它給出了相同的結果。 下面的代碼在 Windows 7 和 Windows Server 2012 之間的輸出不同。在 Windows 7 上,它打印“結果:假”。 在 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();
  }

我還嘗試了以下變體,它在 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();
  }

原來我可以重現這個,在 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();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM