0

I have created a text file using TextWriter C#, on final creation the text file often has various rows of whitespace at the end of the file. The whitespace is not included in any of the string objects that make up the file and I don’t know what is causing it. The larger the file the more whitespace there is.

I've tried various tests to see if the whitespace occurs based upon the content on the string, but this is not the case. i.e. I have identified the number of rows where the whitespace starts and changed the string for something completely different but the whitespace still occurs.

//To start:
MemoryStream memoryStream = new MemoryStream();
TextWriter tw = new StreamWriter(memoryStream);

//Loop through records & create a concatenated string object
string strUTL1 = string.Format("{0}{1}{2}{3}{4}{5}{6}{7}", strUTL1_1, strUTL1_2, strUTL1_3, strUTL1_4, strUTL1_5, strUTL1_6, strUTL1_7, strUTL1_8);

//Add the line to the text file
tw.WriteLine(strUTL1);

//Once all rows are added I complete the file
tw.Flush();
tw.Close();


//Then return the file
return File(memoryStream.GetBuffer(), "text/plain", txtFileName);

I don't want to manipulate the file after completion (e.g. replace blank spaces), as this could lead to other problems. The file will be exchanged with a third party and needs to be formatted exactly.

Thank you for your assistance.

Steven
  • 177
  • 1
  • 10
  • if your total lines is not too high, you can generate the complete file contents in memory using `StringBuilder` and use `File.WriteAllText` to write it in a single operation. – mcy Aug 28 '19 at 10:20

3 Answers3

3

As the doc for MemoryStream.GetBuffer explains:

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.

Use .ToArray() (which will allocate a new array of the right size), or you can use the buffer returned from .GetBuffer() but you'll need to check the .Length to see how many valid bytes are in it.

canton7
  • 37,633
  • 3
  • 64
  • 77
1

GetBuffer() returns all the memory that was allocated, which is almost always more bytes than what you actually wrote into it.

Might I suggest using Encoding.UTF8.GetBytes(...) instead:

string strUTL1 = string.Format("{0}{1}{2}{3}{4}{5}{6}{7}", strUTL1_1, strUTL1_2, strUTL1_3, strUTL1_4, strUTL1_5, strUTL1_6, strUTL1_7, strUTL1_8);

var bytes = Encoding.UTF8.GetBytes(strUTL1);

return File(bytes, "text/plain", txtFileName);
Peter B
  • 22,460
  • 5
  • 32
  • 69
0

Use ToArray() instead of GetBuffer(), since the buffer is larger than needed.

That's often the case. Classes or functions that work with buffers usually reserve a certain size of memory to hold the data. The function will then return a value, how many bytes have been written to the buffer. You shall then only use the first n bytes of the buffer.

Citation of MSDN:

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.

Thomas Weller
  • 55,411
  • 20
  • 125
  • 222