StringBuilder Vs StringWriter/StringReader
Недавно я прочитал, что в StringWriter
и StringReader
используются для записи и чтения из StringBuilder
.
Хорошо, когда я использую StringBuilder
Object, он выглядит как самодостаточный класс.
У нас есть все возможности для чтения и записи StringBuilder
, используя
StringBuilder.Append()
, Insert()
, Replace()
, Remove()
и т.д.
- Какое возможное использование
StringWriter
и StringReader
, которое не может быть выполнено самим StringBuilder
?
- Каково их практическое применение?
- Какова возможная причина, по которой они не принимают
Stream
в качестве входа (поскольку любой другой писатель и считыватель берут поток в качестве параметра конструктора для работы), но StringBuilder
?
Ответы
Ответ 1
Какое возможное использование StringWriter и StringReader, которое не может быть выполнено самим StringBuilder?
StringReader
и StringWriter
вытекают из TextReader
и TextWriter
соответственно. Так что они могут действовать как экземпляр TextReader
или TextWriter
, который string
или StringBuilder
не может, поскольку они не выводят ни один из этих типов.
Каково их практическое применение?
Они позволяют вам вызывать API, ожидающие TextReader
или TextWriter
, когда то, что у вас есть, - это string
или StringBuilder
.
Какова может быть причина, по которой они не принимают поток в качестве входного сигнала (поскольку любой другой писатель и считыватель берут поток в качестве параметра конструктора для работы), но StringBuilder?
Потому что они не работают в потоках; они работают на string
или StringBuilder
s. Они просто простые классы-оболочки, которые адаптируют эти типы для API-интерфейсов, ожидающих другого интерфейса. См. шаблон адаптера.
Ответ 2
Другие уже сказали, но это потому, что они происходят из TextReader/TextWriter и могут использоваться вместо них. Во-первых, имеет смысл использовать один и тот же метод для вывода строк, которые вы используете для файла, если вы хотите, чтобы контент был как строка. Если вам нужен вывод, который будет охватывать несколько строк в памяти, зачем беспокоиться о том, чтобы поместить "\ r\n" в конце каждой строки с помощью StringBuilder? Что делать, если вы хотите, чтобы код запускал или форматировал данные для системы, которая использует "\n" для разрывов строк?
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 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);
Предположим, вы хотите обработать файл по строкам, вы, вероятно, используете StreamReader вместо того, чтобы загружать весь файл в StringBuilder и разделять его символами новой строки в массив, не так ли? С помощью StringReader вы можете использовать тот же самый метод (до тех пор, пока он принимает общий TextReader), создав StringReader из строки из TextBox или веб-формы.
Linq2Sql DataContexts имеют свойство Log, которое вы можете установить в TextWriter для вывода ваших запросов до их выполнения, чтобы точно увидеть, что выполняется. Вы можете установить это в TextWriter, прикрепленный к файлу, но вы можете прикрепить к нему StringWriter и вывести содержимое в нижней части своей веб-страницы при тестировании...
Ответ 3
Я не уверен, кто сказал вам, что их назначение предназначено для использования с StringBuilder, но это абсолютно неверно. Как вы заметили, StringBuilder можно читать и записывать без использования другого класса. Классы StringWriter и StringReader расширяют базовые классы TextReader и TextWriter.Net Framework и предоставляют потоковые функции для работы с текстовыми данными. Например, если вам нужно работать с некоторыми классами типа XmlDocument, некоторые из методов позволяют загружать данные Xml через TextReader, поэтому, если у вас есть текст Xml как строковая переменная, вы можете загрузить его в StringReader а затем поставьте его в XmlDocument.
Ответ 4
Вы можете использовать StringReader для чтения всех целых чисел из строки.
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);
}
}
}
Класс стандартного ввода:
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();
}
}