Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lots of unexpected "nul" caracters at the end of an xml with MemoryStream

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.

like image 646
Sharpac Avatar asked Apr 18 '13 14:04

Sharpac


1 Answers

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.

like image 173
Jon Skeet Avatar answered Nov 15 '22 00:11

Jon Skeet