MemoryStream искажает мой XML? msgstr "шестнадцатеричное значение 0x0 недопустимо в документах XML." - PullRequest
1 голос
/ 28 февраля 2010

Я действительно новичок с потоками, поэтому я не знаю, что я здесь делаю. :)

У меня есть XElement, содержащий XML. Я хочу вернуть его как файл пользователю.

  XElement xml = IndicesXMLGenerator.XML();

  //Code for creating a memorystream for returning to browser as file
   MemoryStream stream = new MemoryStream();
  XmlTextWriter writer = new XmlTextWriter(stream, System.Text.Encoding.Unicode);
  xml.Save(writer);
  writer.Close();

  //Code for direct saving to harddisk
  FileStream filestream = new FileStream(@"D:\indices.xml", FileMode.Create);
  XmlTextWriter writer2 = new XmlTextWriter(filestream, System.Text.Encoding.Unicode);
  xml.Save(writer2);
  writer2.Close();
  filestream.Close();

  //Return memorystream as fileresult
  return base.File(new MemoryStream(stream.GetBuffer()), "text/xml", "AlleIndices.xml");
    }

Когда я открываю файл, полученный из браузера, он полностью искажен. как: �< ? X M L

Когда я меняю кодировку в коде на UTF8, это дает мне документ нормального вида, но в конце я получаю много символов 0x0, которые делают документ недействительным.

Странно то, что XML-файл, который я сохранил непосредственно на жестком диске из кода:

  • Отлично в кодировке
  • Не содержит странных 0x0 символов

Итак, что здесь происходит? Почему я не могу легко передать свой XElement в браузер в виде файла?

Ответы [ 4 ]

2 голосов
/ 28 февраля 2010

Вызов GetBuffer вернет внутренний буфер потока, который будет больше, чем фактические данные. (На случай, если вы напишете еще что-нибудь в поток)

Вам необходимо заменить вызов GetBuffer на ToArray(), что скопирует использованную часть буфера в новый массив.


Однако лучший способ сделать это - вернуть исходный MemoryStream, но сначала установить для свойства Position значение 0, например:

stream.Position = 0;
return File(stream, "text/xml", "AlleIndices.xml");
1 голос
/ 28 февраля 2010
  1. Вам не нужно создавать новый MemoryStream, вы можете просто использовать то же самое (вам просто нужно Seek до начала потока)

  2. XML выглядит искаженным, потому что браузер не знает, что он закодирован как Unicode. В ответ необходимо добавить заголовок Content-Encoding , чтобы указать кодировку

0 голосов
/ 02 марта 2010

В конечном итоге вы будете намного счастливее, если напишите свой код так:

XElement xml = IndicesXMLGenerator.XML();
using (MemoryStream ms = new MemoryStream())
using (XmlWriter xw = XmlWriter.Create(ms))
{
   xml.Save(xw);
}
  1. Используйте XmlWriter.Create, а не XmlTextWriter, и используйте XmlWriterSettings для управления кодированием и форматированием.
  2. Используйте using блоки вместо явного вызова Flush и Close - так вам не нужно явно вызывать их.

Тем не менее, на самом деле это не ваша проблема, которая, как отмечалось, заключается в использовании GetBuffer вместо ToArray. Но, как я уже сказал, в конечном итоге вы будете счастливее.

0 голосов
/ 28 февраля 2010

MemoryStream реализует метод удвоения массива, чтобы он мог эффективно изменять размер при добавлении байтов. Это означает, что буфер обычно больше, чем фактические данные.

Есть несколько решений:

  1. Используйте ToArray вместо GetBuffer.
  2. Используйте конструктор MemoryStream, который принимает смещение и длину.

Например:

new MemoryStream(stream.GetBuffer(), 0, (int)stream.Length)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...