2013-10-21 31 views
11

Edit: Ich dachte ursprünglich, dies war mit .NET Framework 4.5 verwandt. Es stellte sich heraus, dass es auch für .NET Framework 4.0 gilt.StartsWith Änderung in Windows Server 2012

Es gibt eine Änderung, wie Zeichenfolgen in Windows Server 2012 behandelt werden, die ich versuche, besser zu verstehen. Es scheint, als ob sich das Verhalten von StartsWith geändert hat. Das Problem ist unter Verwendung von .NET Framework 4.0 und 4.5 reproduzierbar.

Mit .NET Framework 4.5 unter Windows 7 druckt das folgende Programm "False, t". Auf Windows 2012 Server wird stattdessen "True, t" ausgegeben.

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

Mit anderen Worten, gibt Starts (ByteOrderMark) gilt unabhängig von String-Inhalt. Wenn Sie Code haben, der die Bytereihenfolgemarkierung mit dem folgenden Verfahren zu abzustreifen versucht weg, wird dieser Code funktionieren mit Windows 7, sondern druckt „est“ unter 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 Stellen Sie fest, dass Sie bereits etwas falsch gemacht haben, wenn Sie Byte Order Markers in einer Zeichenfolge haben, aber wir integrieren mit Legacy-Code, der dies hat. Ich weiß, dass ich dieses spezifische Problem lösen kann, indem ich etwas wie unten tue, aber ich möchte das Problem besser verstehen.

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

Hans Passsant vorgeschlagen, den Konstruktor von UTF8Encoding verwendet, die mich ausdrücklich Kennung auszusenden UTF8 sagen lässt. Ich habe das versucht, aber es gibt das gleiche Ergebnis. Der folgende Code unterscheidet sich in der Ausgabe zwischen Windows 7 und Windows Server 2012. Unter Windows 7 wird "Ergebnis: Falsch" ausgegeben. Auf Windows Server 2012 wird "Result: True" ausgegeben.

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

Ich habe auch versucht, die folgende Variante, die zur Umsetzung der Starts auf Windows Server 2012 falsch, falsch, falsch auf Windows 7, aber wahr, True, False druckt auf Windows Server 2012, die im Zusammenhang es bestätigt Stellt sich.

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

ich nicht einmal 'Trim' verwenden würde - wenn Sie besorgt über die * erste Zeichen sind * dann überprüft nur, ob' Text [0] == ‚\ ufeff '' wäre gut genug (mit passender Handhabung für eine leere Saite). Sieht jedoch seltsam aus. –

+0

Sicher, das würde besser funktionieren als Trim. Angenommen, TrimStart würde auch gut funktionieren. Trotzdem versuche ich hauptsächlich zu verstehen, warum sich das geändert hat. Bei vielen der Antworten auf dieser Website wird vorgeschlagen, zunächst mit StartsWith() zu überprüfen, dass dieser Code bei der Ausführung unter Windows Server 2012 mit .NET Framework 4.5 nicht mehr funktioniert. Beispiel hier: http://stackoverflow.com/questions/1317700/strip-byte-order-mark-from-string-in-c-sharp. – Nitramk

Antwort

10

I konnte repro dies, das Testprogramm auf Windows 8.1 ausgeführt wird. Es ist in der gleichen "Familie" wie Server 2012.

Die wahrscheinlichste Quelle des Problems ist, dass sich die kultursensitiven Vergleichsregeln geändert haben. Sie können, äh, flockige sein und können ungerade Ergebnisse auf diese Art von Zeichen haben. Die Stückliste ist ein Raum mit null Breite. Um dies zu verstehen, muss man dieselbe mentale Gymnastik machen wie das Verständnis, warum "abc" .StartsWith ("") wahr zurückgibt :)

Sie müssen Ihr Problem lösen, indem Sie StringComparison.Ordinal verwenden. Dies erzeugte Falsch, falsch, falsch:

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

Es stellt sich heraus, dass das Problem für mich auch mit .NET Framework 4.0 reproduzierbar ist.Ich habe meinen Hauptbeitrag aktualisiert, um ein neues Snippet basierend auf Ihrem Vorschlag hinzuzufügen, aber es gibt ein anderes Verhalten zwischen Windows 7 und Windows Server 2012. Ich habe auch ein Snippet hinzugefügt, wo ich \ ufeff hartcode und übergebe es an StartsWith und das Verhalten gesehen unterscheidet sich zwischen Windows 7 und Windows 2012 Server. Ich stimme zu, dass dies seltsam ist, aber es ist, was ich sehe. – Nitramk

+0

Super, danke! Nicht wirklich intuitiv, aber macht Sinn. – Nitramk

+0

Ihr habt meinen Speck gerettet! BTW konnte ich einfach mit 'string byteOrderMarkUtf8 = Encoding.UTF8.GetString (Encoding.UTF8.GetPreamble()); 'auf Windows Server 2012, gefolgt von Ihrem entscheidenden' StartsWith (byteOrderMarkUtf8, StringComparison.Ordinal)' durchkommen. – snark

Verwandte Themen