tmaj
tmaj

Reputation: 34987

Writing the content of StringBuilder to a file without calling ToString()

Let's imagine that I have a StringBuilder and I cannot refactor it to use a stream. I want to write the content of my StrinBuilder to a file but I don't want to make an extra copy of the content in memory i.e I don't want to call ToString().

Can I get the content without making an extra copy in memory ?

I believe that prior to version 2 ToString() could avoid copying by using copy on write, but this no longer is the case.

Upvotes: 5

Views: 5839

Answers (3)

wlf
wlf

Reputation: 3393

Writing 1 byte at a time can be very slow for large strings, so implementing hvd's suggestion of StringBuilder.CopyTo(..):

 using (StreamWriter sw = new StreamWriter(FilePath))
 {
     const int bufferSize = 10000;
     char[] buffer = new char[bufferSize];

     for (int i = 0; i < builder.Length; i += bufferSize)
     {
         int count = Math.Min(bufferSize, builder.Length - i);
         builder.CopyTo(i, buffer, 0, count);
         sw.Write(buffer, 0, count);
     }
 }

Upvotes: 6

user743382
user743382

Reputation:

If I understand your question correctly, it's not about making a copy per se, it's about making a copy of the whole thing at once. In other words, if you have a multi-megabyte StringBuilder, avoid requiring a multi-megabyte allocation just to store that to disk.

If that is correct, you can use StringBuilder.CopyTo with a smaller fixed-size buffer to copy the data out in blocks. You can then write those smaller blocks directly to any stream you like.

Upvotes: 6

fubo
fubo

Reputation: 45947

you can avoid the ToString() by accessing the char elements of the StringBuilder by index

StringBuilder sb = new StringBuilder();
// fill StringBuilder 
using (StreamWriter sw = new StreamWriter(@"c:\file.txt"))
{
    for (int i = 0; i < sb.Length; i++)
    {
        sw.Write(sb[i]);
    }
}

Upvotes: 4

Related Questions