Reputation: 34987
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
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
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
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