StringBuilder Vs StringWriter/StringReader
I recen开发者_StackOverflow社区tly 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...
- What is the possible use of
StringWriter
andStringReader
, which cannot be done byStringBuilder
itself? - What is the practical use of them?
- 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 theStringBuilder
?
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 string
s or StringBuilder
s. They're just simple wrapper classes that adapt these types for APIs expecting a different interface. See: adapter pattern.
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...
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();
}
}
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.
精彩评论