Подтвердить что ты не робот

StringBuilder Vs StringWriter/StringReader

Недавно я прочитал, что в StringWriter и StringReader используются для записи и чтения из StringBuilder.

Хорошо, когда я использую StringBuilder Object, он выглядит как самодостаточный класс.

У нас есть все возможности для чтения и записи StringBuilder, используя StringBuilder.Append(), Insert(), Replace(), Remove() и т.д.

  • Какое возможное использование StringWriter и StringReader, которое не может быть выполнено самим StringBuilder?
  • Каково их практическое применение?
  • Какова возможная причина, по которой они не принимают Stream в качестве входа (поскольку любой другой писатель и считыватель берут поток в качестве параметра конструктора для работы), но StringBuilder?
4b9b3361

Ответ 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();
    }
}