2013-10-21 9 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上で正常に動作しますが、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 Windows上で「EST」を印刷します文字列にバイトオーダーのマーカーがある場合は、すでに間違っていたことに気がつきますが、これを持つレガシーコードと統合しています。私はこのような問題を以下のようにして解決できることを知っていますが、問題をよりよく理解したいと思います。

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

ハンスPasssantは私がUTF8識別子を発するように明示的に伝えることができますUTF8Encodingのコンストラクタを使用して提案しました。私はこれを試みたが、同じ結果を与える。以下のコードは、Windows 7とWindows Server 2012の出力が異なります.Windows 7では、「結果:False」と表示されます。 Windows Server 2012では、「結果: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 Server 2012上のSTARTSWITHの実施に関連しています確認のWindows Server 2012、上の偽のWindows 7上の偽しかし真、真、偽偽印刷し、以下の変異体を、試してみました。

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でのテストプログラムを実行し、これをI でし REPROをオンにします。サーバー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の間で異なる振る舞いをしています。スニペットを追加してハードコードし、\ begin {表示されるWindows 7とWindows 2012 Serverは異なります。私はこれが奇妙であることに同意するが、それは私が見ているものだ。 – Nitramk

+0

恐ろしく、ありがとう!本当に直感的ではありませんが、意味があります。 – Nitramk

+0

皆さんは私のベーコンを救った! BTW私は、Windows Server 2012で単純に 'string byteOrderMarkUtf8 = Encoding.UTF8.GetPreamble());'を打ち消し、重要な 'StartsWith(byteOrderMarkUtf8、StringComparison.Ordinal)'を追い出すことができました。 – snark

関連する問題