5

I wrote an action for a user to downoad a generated xml generated whithout having to write it on the server disk, but keep it into memory.

Here is my code :

public FileContentResult MyAction()
{
  MemoryStream myStream = new MemoryStream();
  XDocument xml = GenerateXml(...);
  xml.Save(myStream );
  myStream .Position = 0;
  return File(myStream.GetBuffer(), "text/xml", "myFile.xml");
}

Everything seem to work fine, the XML is correct, I can download the file, but I don't understand why I have 691920 "nul" caracters at the end of my file (the number of those caracters seems to be related to the length of the xml):

enter image description here

Where do they came from ? How can I rid of them ?

[Update] I tried this :

public FileContentResult MyAction()
{
  XDocument xml = GenerateXml(...);
  byte[] bytes = new byte[xml.ToString().Length * sizeof(char)];
  Buffer.BlockCopy(xml.ToString().ToCharArray(), 0, bytes, 0, bytes.Length);
  return File(bytes, "text/xml", "myFile.xml");
}

And I didn't get the "nul" characters. So I suppose it is the MemoryStream which add extra caracters at the end of the file. So in my example whith the second code my problem is solved.

But I also generate a Word document which I can't read (xxx.docx cannot be opened because there are problems with the contents). I suppose I have the same problem here, the memory stream add extra caracters at the end of the file and corrupt it.

Sharpac
  • 378
  • 3
  • 4
  • 13

1 Answers1

11

The problem is that you're calling myStream.GetBuffer(). The GetBuffer() method returns the underlying array used by the MemoryStream, including any "spare" parts which don't contain real data. From the documentation:

Note that the buffer contains allocated bytes which might be unused. For example, if the string "test" is written into the MemoryStream object, the length of the buffer returned from GetBuffer is 256, not 4, with 252 bytes unused. To obtain only the data in the buffer, use the ToArray method; however, ToArray creates a copy of the data in memory.

Instead of using GetBuffer(), use ToArray() - or use the length of the stream to know how much of the buffer to actually use.

Note that in your updated code, you're basically converting the string to UTF-16 - which may well mean that it's twice the size it needs to be, and it may also not be following the encoding it claims. I wouldn't recommend that approach.

Jon Skeet
  • 1,261,211
  • 792
  • 8,724
  • 8,929