Каждый открытый файл имеет связанную позицию. Когда вы читаете (), вы читаете с этой позиции. Например, read(10)
считывает первые 10 байт из вновь открытого файла, затем другой read(10)
считывает следующие 10 байтов. read()
без аргументов считывает все содержимое файла, оставляя позицию файла в конце файла. В следующий раз, когда вы вызываете read()
, читать нечего.
Вы можете использовать seek
для перемещения позиции файла. Или, вероятно, лучше в вашем случае было бы сделать один read()
и сохранить результат для обоих поисков.
Если переменная xml относится к типу string, значит, вы уже сделали что-то не так - в символьной строке спецификация должна быть представлена не как три отдельных символа, а как одна кодовая точка . Вместо использования DownloadString используйте DownloadData и анализируйте массивы байтов. Синтаксический анализатор XML должен распознавать саму спецификацию и пропускать ее (за исключением автоматического определения кодировки документа как UTF-8).
Еще одно универсальное изменение для избавлений от преамбулы BOM UTF-8:
var preamble = Encoding.UTF8.GetPreamble();
if (!functionBytes.Take(preamble.Length).SequenceEqual(preamble))
preamble = Array.Empty<Byte>();
return Encoding.UTF8.GetString(functionBytes, preamble.Length, functionBytes.Length - preamble.Length);
Я решил проблему со следующим кодом
using System.Xml.Linq;
void method()
{
byte[] bytes = GetXmlBytes();
XDocument doc;
using (var stream = new MemoryStream(docBytes))
{
doc = XDocument.Load(stream);
}
}
Передайте байтовый буфер (через DownloadData) в строку Encoding.UTF8.GetString (byte [])
, чтобы получить строку, а не загружать буфер как строку. У вас, вероятно, больше проблем с вашим текущим методом, чем просто обрезка метки порядка байтов. Если вы правильно не декодируете его, как я предлагаю здесь, символы Unicode, вероятно, будут неправильно истолкованы, что приведет к повреждению строки.
Изменить : Ответ Мартина лучше, поскольку он позволяет избежать выделения всей строки для XML, который все еще нуждается все равно быть проанализированным. Ответ, который я дал, лучше всего подходит для общих строк, которые не нужно анализировать как XML.
У меня были неверные данные теста, что вызвало у меня некоторое замешательство. Основываясь на Как избежать спотыкания о спецификации UTF-8 при чтении файлов Я обнаружил, что это сработало:
private readonly string _byteOrderMarkUtf8 =
Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
public string GetXmlResponse(Uri resource)
{
string xml;
using (var client = new WebClient())
{
client.Encoding = Encoding.UTF8;
xml = client.DownloadString(resource);
}
if (xml.StartsWith(_byteOrderMarkUtf8, StringComparison.Ordinal))
{
xml = xml.Remove(0, _byteOrderMarkUtf8.Length);
}
return xml;
}
Правильная установка клиентского свойства Encoding сокращает BOM до одного символа. Однако XDocument.Parse по-прежнему не будет читать эту строку. Это самая чистая версия, которую я когда-либо придумал.
Это тоже работает
int index = xmlResponse.IndexOf('<');
if (index > 0)
{
xmlResponse = xmlResponse.Substring(index, xmlResponse.Length - index);
}