StringBuilder Vs StringWriter/StringReader
Asked Answered
L

4

36

I recently read that in StringWriter and StringReader are used for writing and reading from StringBuilder.

Well when I use StringBuilder Object, it looks to be a self sufficient class.

We have every way of reading and writing the StringBuilder, using StringBuilder.Append(), Insert(), Replace(), Remove() etc...

  1. What is the possible use of StringWriter and StringReader, which cannot be done by StringBuilder itself?
  2. What is the practical use of them?
  3. What could be the possible reason they are not taking up Stream as the input (Because any other writer and reader are taking the stream as the Constructor parameter to operate on) but the StringBuilder?
Lacagnia answered 3/8, 2010 at 0:26 Comment(1)
Possible duplicate of StringWriter or StringBuilderSizing
I
37

What is the possible use of StringWriter and StringReader, which cannot be done by StringBuilder itself?

StringReader and StringWriter derive from TextReader and TextWriter respectively. So what they can do act as a TextReader or TextWriter instance, which string or StringBuilder cannot because they do not derive either of those types.

What is the practical use of them?

They allow you to call APIs that are expecting a TextReader or TextWriter, when what you have/want is a string or StringBuilder.

What could be the possible reason they are not taking up Stream as the input (Because any other writer and reader are taking the stream as the Constructor parameter to operate on) but the StringBuilder?

Because they don't work on streams; they work on strings or StringBuilders. They're just simple wrapper classes that adapt these types for APIs expecting a different interface. See: adapter pattern.

Ignite answered 3/8, 2010 at 0:38 Comment(0)
A
7

Others have said already, but it is because they derive from TextReader/TextWriter and can be used in place of them. For one thing it just makes more sense to use the same method for outputting lines that you use for a file if you only want the content as a string. If you want output that will span multiple lines in memory, why bother remembering to put "\r\n" at the end of every line with a StringBuilder? What if you want the code to run on or format data for a system that only uses "\n" for line breaks?

StringBuilder sb = new StringBuilder();
// will be invalid on systems that only use \n
sb.AppendFormat("{0:yyyy-MM-dd HH:mm:ss} - Start\r\n", DateTime.Now);
// still have to add an extra parameter
sb.AppendFormat("The current time is {0:yyyy-MM-dd HH:mm:ss}{1}", DateTime.Now,
    Environment.NewLine);

StringWriter sw = new StringWriter();
// Don't have to worry about it, method name tells you there's a line break
sw.WriteLine("{0:yyyy-MM-dd HH:mm:ss} - Start", DateTime.Now);
// no extra parameters
sw.WriteLine("The current time is {0:yyyy-MM-dd HH:mm:ss}", DateTime.Now);

Say you want to process a file line by line, you would probably use a StreamReader instead of loading the whole file into a StringBuilder and splitting it by newline characters into an array, right? With StringReader you can use the exact same method (as long as it takes a generic TextReader) by creating the StringReader from a string from a TextBox or web form.

Linq2Sql DataContexts have a Log property you can set to a TextWriter to have your queries output before they are executed to see exactly what is being run. You can set this to a TextWriter attached to a file, but you could attach a StringWriter to it and output the contents at the bottom of your web page when testing...

Atwell answered 30/11, 2010 at 4:47 Comment(1)
StringBuilder has an AppendLine method that adds a newline at the endMelena
G
1

You can use StringReader to read all integers from a string.

private static void Main()
{
    var str = @"
                13
                13
                0 6
                0 5
                0 1
                0 2
                5 3
                6 4
                5 4
                3 4
                7 8
                9 10
                11 12
                9 11
                9 12";


    using (StandardInput input = new StandardInput(new StringReader(str)))
    {
        List<int> integers = new List<int>();
        int n;
        while ((n = input.ReadInt32()) != -1)
        {
            integers.Add(n);
        }
    }
}

StandardInput Class:

class StandardInput : IDisposable
{
    private readonly TextReader reader;

    public StandardInput(TextReader reader)
    {
        this.reader = reader;
    }

    public int ReadInt32()
    {
        while (!char.IsDigit((char)reader.Peek()) && reader.Peek() != -1)
        {
            reader.Read();
        }
        var builder = new StringBuilder();
        while (char.IsDigit((char) reader.Peek()))
            builder.Append((char) reader.Read());

        return builder.Length == 0 ? -1 : int.Parse(builder.ToString());
    }

    public double ReadDouble()
    {
        while (!char.IsDigit((char)reader.Peek()) && reader.Peek() != '.'
                                                  && reader.Peek() != -1)
        {
            reader.Read();
        }
        var builder = new StringBuilder();
        if (reader.Peek() == '.')
            builder.Append((char) reader.Read());
        while (char.IsDigit((char)reader.Peek()))
            builder.Append((char)reader.Read());
        if (reader.Peek() == '.' && !builder.ToString().Contains("."))
        {
            builder.Append((char)reader.Read());
            while (char.IsDigit((char)reader.Peek()))
                builder.Append((char)reader.Read());
        }
        return builder.Length == 0 ? -1 : double.Parse(builder.ToString());
    }

    public void Dispose()
    {
        reader.Dispose();
    }
}
Geese answered 8/9, 2014 at 13:35 Comment(0)
E
0

I'm not sure who told you that their purpose was for use with StringBuilder, but that is absolutely incorrect. As you noted StringBuilder can be read from and written to without the use of another class. The StringWriter and StringReader classes extend the TextReader and TextWriter .Net Framework base classes and provide stream-like features for working with textual data. For example, if you need to work with some of the XmlDocument-type classes some of the methods allow you to load the Xml data via a TextReader, so if you have the Xml text as a string variable, you could load it into a StringReader and then supply it to the XmlDocument.

Epergne answered 3/8, 2010 at 0:35 Comment(2)
Hi, thank you for your answer. I agree to the point that its derived from TextWriter/TextReader. I have taken StringWriter for instance and found both of the following initializations doesn't work. FileStream fs = new FileStream(@"C:\Users\Saravanan\Documents\something.bin", FileMode.OpenOrCreate); StringWriter sw1 = File.CreateText(@"C:\Users\Saravanan\Documents\something.bin"); StringWriter sw2 = new StringWriter(fs); It takes only Stringbuilder to write.Lacagnia
@Saravanandss - If you're trying to read/write from/to streams, then use StreamReader and StreamWriter... that's what they're there for. StringReader and StringWriter are not designed for working with files; they're designed for working with strings. Why are you trying to use them?Ignite

© 2022 - 2024 — McMap. All rights reserved.