Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Write StringBuilder to Stream

What is the best method of writing a StringBuilder to a System.IO.Stream?

I am currently doing:

StringBuilder message = new StringBuilder("All your base");
message.Append(" are belong to us");

System.IO.MemoryStream stream = new System.IO.MemoryStream();
System.Text.ASCIIEncoding encoding = new ASCIIEncoding();
stream.Write(encoder.GetBytes(message.ToString()), 0, message.Length);
like image 695
Andy Joiner Avatar asked Feb 10 '10 11:02

Andy Joiner


5 Answers

Don't use a StringBuilder, if you're writing to a stream, do just that with a StreamWriter:

using (var memoryStream = new MemoryStream())
using (var writer = new StreamWriter(memoryStream ))
{
    // Various for loops etc as necessary that will ultimately do this:
    writer.Write(...);
}
like image 109
Neil Barnwell Avatar answered Oct 30 '22 01:10

Neil Barnwell


That is the best method. Other wise loss the StringBuilder and use something like following:

using (MemoryStream ms = new MemoryStream())
{
    using (StreamWriter sw = new StreamWriter(ms, Encoding.Unicode))
    {
        sw.WriteLine("dirty world.");
    }
    //do somthing with ms
}
like image 42
particle Avatar answered Oct 30 '22 01:10

particle


Perhaps it will be usefull.

var sb= new StringBuilder("All your money");
sb.Append(" are belong to us, dude.");
var myString = sb.ToString();
var myByteArray = System.Text.Encoding.UTF8.GetBytes(myString);
var ms = new MemoryStream(myByteArray);
// Do what you need with MemoryStream
like image 6
Friend Avatar answered Oct 30 '22 02:10

Friend


Depending on your use case it may also make sense to just start with a StringWriter:

StringBuilder sb = null;

// StringWriter - a TextWriter backed by a StringBuilder
using (var writer = new StringWriter())
{
    writer.WriteLine("Blah");
    . . .
    sb = writer.GetStringBuilder(); // Get the backing StringBuilder out
}

// Do whatever you want with the StringBuilder
like image 5
Chris Moschini Avatar answered Oct 30 '22 00:10

Chris Moschini


EDIT: As @ramon-smits points out, if you have access to StringBuilder.GetChunks(), you will also have access to StreamWriter.WriteAsync(StringBuilder). So you can just do this instead:

StringBuilder stringBuilder = new StringBuilder();
// Write data to StringBuilder...
Stream stream = GetStream(); // Get output stream from somewhere.
using (var streamWriter = new StreamWriter(stream, Encoding.UTF8, leaveOpen: true))
{
    await streamWriter.WriteAsync(stringBuilder);
}

Much simpler.


I recently had to do exactly this thing and found this question with unsatisfactory answers.

You can write a StringBuilder to a Stream without materializing the entire string:

StringBuilder stringBuilder = new StringBuilder();
// Write data to StringBuilder...
Stream stream = GetStream(); // Get output stream from somewhere.
using (var streamWriter = new StreamWriter(stream, Encoding.UTF8, leaveOpen: true))
{
    foreach (ReadOnlyMemory<char> chunk in stringBuilder.GetChunks())
    {
        await streamWriter.WriteAsync(chunk);
    }
}

N.B. This API (StringBuilder.GetChunks()) is only available in .NET Core 3.0 and above

If this operation happens frequently, you could further reduce GC pressure by using a StringBuilder object pool.

like image 5
Jabbersii Avatar answered Oct 30 '22 00:10

Jabbersii