Изменить: изначально я думал, что это связано с .NET Framework 4.5. Оказалось, что это относится и к .NET Framework 4.0.
Там изменилось, как строки обрабатываются в Windows Server 2012, которые я пытаюсь понять лучше. Похоже, что поведение StartsWith изменилось. Эта проблема воспроизводится с использованием как .NET Framework 4.0, так и 4.5.
С .NET Framework 4.5 в Windows 7 программа ниже печатает "False, t". В Windows Server 2003 он печатает "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]);
Hans Passsant предложил использовать конструктор UTF8Encoding, который позволяет мне прямо указывать на то, чтобы испускать идентификатор UTF8. Я пробовал это, но он дает тот же результат. Нижеприведенный код отличается от вывода между 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();
}
Я также пробовал следующий вариант, который печатает False, False, False в Windows 7, но True, True, False в 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();
}