2013-10-21 20 views
11

編輯:我最初認爲這與.NET Framework 4.5有關。原來它也適用於.NET Framework 4.0。開始在Windows Server 2012中進行更改

在我試圖更好地理解的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,但將打印「EST」在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(); 

    } 

}

我意識到如果字符串中有字節順序標記,那麼你已經做了錯誤的事情,但是我們正在與具有這種功能的遺留代碼進行整合。我知道我可以通過做下面的事情來解決這個問題,但我想更好地理解這個問題。

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

漢斯Passsant使用UTF8Encoding的構造,它可以讓我來告訴它明確地發出UTF8標識建議。我嘗試了這一點,但它給出了相同的結果。下面的代碼在Windows 7和Windows Server 2012之間的輸出方面有所不同。在Windows 7上,它輸出「結果:錯誤」。在Windows Server 2012上,它打印出「結果:真」。

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上假,但真正的,真實的,Windows Server 2012中,這證實它涉及到StartsWith的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(); 
    } 
+0

我甚至不會用'Trim' - 如果你只擔心*第一個字符*然後只檢查是否'文本[0] ==「\ ufeff ''會足夠好(通過適當的處理空字符串)。雖然看起來很奇怪。 –

+0

當然,那會比修剪更好。假設TrimStart也會運行良好。我仍然主要試圖理解爲什麼這首先發生了變化。本網站上的許多最新投票響應建議首先使用StartsWith()進行檢查,並且在使用.NET Framework 4.5的Windows Server 2012上運行時,代碼將會崩潰。示例:http://stackoverflow.com/questions/1317700/strip-byte-order-mark-from-string-in-c-sharp。 – Nitramk

回答

10

原來我攝製了,運行在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(); 
} 
+0

事實證明這個問題對我來說也是可重複使用.NET Framework 4.0的。我更新了我的主帖,根據您的建議添加了一個新的代碼片段,但它給出了Windows 7和Windows Server 2012之間的不同行爲。我還添加了一段代碼,在該代碼段中,我將\ ufeff硬編碼並將其傳遞給StartsWith,並將行爲在Windows 7和Windows 2012 Server之間有所不同。我同意這很奇怪,但這是我所看到的。 – Nitramk

+0

真棒,謝謝!不是很直觀,但有一定意義。 – Nitramk

+0

你們救了我的培根!順便說一下,我可以簡單地使用'string byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());'在Windows Server 2012上,然後是關鍵的'StartsWith(byteOrderMarkUtf8,StringComparison.Ordinal)'。 – snark

相關問題