2013-10-21 24 views
11

Düzenleme: Aslında bunun .NET Framework 4.5 ile ilgili olduğunu düşündüm. Bu, .NET Framework 4.0 için de geçerli olduğu ortaya çıktı.Windows Server 2012'de başlatılan değişikliklerWindows Server 2012

Windows Server 2012'de dizeleri nasıl daha iyi anlamaya çalıştığımı değiştirme konusunda bir değişiklik var. StartsWith'in davranışları değişmiş gibi görünüyor. Sorun, hem .NET Framework 4.0 ve 4.5 kullanılarak yeniden üretilebilir.

Windows 7'de .NET Framework 4.5 ile aşağıdaki program "False, t" yazdı. Windows 2012 Server'da, bunun yerine "True, t" yazdırır.

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

Başka bir deyişle, StartsWith (ByteOrderMark), dize içeriğinden bağımsız olarak true değerini döndürür. aşağıdaki yöntemi kullanarak bayt sırası işareti sıyırıp çalışan kod varsa, bu kod Windows 7 ile iyi çalışır fakat 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(); 

    } 

}

Windows üzerinde "est" yazdırır Bir dizede bayt sırası işaretçileri varsa, yanlış bir şey yaptığınızı fark edersiniz, ancak buna sahip olan eski kod ile bütünleşiyoruz. Bu özel sorunu aşağıda olduğu gibi çözerek çözebileceğimi biliyorum, ancak sorunu daha iyi anlamak istiyorum.

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

Hans Passsant beni UTF8 tanımlayıcı yayacak şekilde açıkça anlatmak sağlar UTF8Encoding yapıcısı kullanılarak önerdi. Bunu denedim, ama aynı sonucu veriyor. Aşağıdaki kod Windows 7 ve Windows Server 2012 arasındaki çıktıda farklılık gösterir. Windows 7'de "Sonuç: Yanlış" yazdırır. Windows Server 2012'de "Sonuç: Doğru" yazdırır.

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

Ben de Windows Server 2012'de startswith uygulanmasına alakalı teyit Windows Server 2012, False Windows 7 Yanlış ama Doğru, Doğru, Yanlış Yanlış yazdırır aşağıdaki varyantı,, denedim .

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

Hatta 'Trim' kullanmak ister - Eğer * İlk karakteri hakkında sadece endişeli iseniz * sonra sadece kontrol' olmadığını metin [0] == '\ ufeff '' yeterince iyi (boş bir dize için uygun elleçleme ile). Yine de tuhaf görünüyor. –

+0

Elbette, bu Trim'den daha iyi çalışırdı. TrimStart'ın da işe yarayacağını varsayalım. Yine de çoğunlukla bunun neden ilk başta değiştiğini anlamaya çalışıyorum. Bu sitedeki en çok okunan yanıtların bir kısmı, ilk olarak StartsWith() ile kontrol edilmesini ve Windows Server 2012'de .NET Framework 4.5 ile çalıştırıldığında bu kodun bozulacağını önerir. Örnek burada: http://stackoverflow.com/questions/1317700/strip-byte-order-mark-from-string-in-c-sharp. – Nitramk

cevap

10

Windows 8.1'de test programı çalıştıran, bu şimdiye olabilir Repro çıkıyor. Bu, Server 2012 ile aynı "aile" dir.

Sorunun en olası kaynağı, kültüre duyarlı karşılaştırma kurallarının değişmiş olmasıdır. Bunlar erm, pul pul olabilir ve bu tür karakterler üzerinde garip sonuçlar doğurabilir. BOM sıfır genişlikte bir alan. Bunu akılda tutmanın nedeni, "abc" nedenini anlamak için aynı türden zihinsel jimnastiğe ihtiyaç duymaktadır. StartsWith ("") true döndürür :)

Sorununuzu StringComparison.Ordinal kullanarak çözmeniz gerekir. Bu yanlış, Yanlış, Yanlış üretti:

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

Bu sorun, .NET Framework 4.0 ile de benim için yeniden üretilebilir.Ana sayfamı önerinize dayalı yeni bir snippet'i dahil etmek için güncelledim, ancak Windows 7 ve Windows Server 2012 arasında farklı davranışlar veriyor. Ayrıca sabit kod \ ufeff ve StartsWith'e ve davranışa geçtiğim bir snippet ekledim. görülen Windows 7 ve Windows 2012 Server arasında farklıdır. Buna garip geldiğine katılıyorum ama görüyorum. – Nitramk

+0

Harika, teşekkürler! Gerçekten sezgisel değil, ama biraz mantıklı. – Nitramk

+0

Siz pastırmamı kurtardınız! BTW Ben basitçe ile dize byteOrderMarkUtf8 = Encoding.UTF8.GetString (Encoding.UTF8.GetPreamble()); 'Windows Server 2012'de, sonra sizin için önemli olan StartsWith (byteOrderMarkUtf8, StringComparison.Ordinal)'. – snark