Начинается с изменения в Windows Server 2012
Изменить: я изначально думал, что это связано с .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 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]);
Ханс Пассант предложил использовать конструктор 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();
}
Я также попробовал следующий вариант, который печатает 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();
}