// Отобразить содержимое массива storage непосредственно.
foreach(char ch in storage) {
if (ch == '.') break;
Console.Write(ch);
}
Console.WriteLine("\nЧтение из потока с помощью объекта memrdr: ");
// Читать из объекта memstrm средствами
// ввода данных из потока,
memstrm.Seek(0, SeekOrigin.Begin); // -установить указатель файла
// в исходное положение
string str = memrdr.ReadLine();
while(str != null) {
str = memrdr.ReadLine();
if(str[0] == '.') break;
Console.WriteLine(str);
}
} catch(IOException exc) {
Console.WriteLine("Ошибка ввода-вывода" + exc.Message);
} finally {
// Освободить ресурсы считывающего и записывающего потоков,
memwtr.Close();
memrdr.Close() ;
}
}
}
Вот к какому результату приводит выполнение этой программы.
Чтение прямо из массива storage:
byte [0]: 0
byte [1]: 1
byte [2]: 2
byte [3]: 3
byte [4]: 4
byte [5]: 5
byte [6]: 6
byte [7]: 7
byte [8]: 8
byte [9]: 9
Чтение из потока с помощью объекта memrdr:
byte [1]: 1
byte [2]: 2
byte [3]: 3
byte [4]: 4
byte [5]: 5
byte [6]: 6
byte [7]: 7
byte [8]: 8
byte [9]: 9
В этой программе сначала создается массив байтов, называемый storage. Затем этот массив используется в качестве основной памяти для объекта memstrm
класса MemoryStream
. Из объекта memstrm
, в свою очередь, создаются объекты memrdr
класса StreamReader
и memwtr
класса StreamWriter
. С помощью объекта memwtr
выводимые данные записываются в запоминающий поток. Обратите внимание на то, что после записи выводимых данных для объекта memwtr вызывается метод Flush()
. Это необходимо для того, чтобы содержимое буфера этого объекта записывалось непосредственно в базовый массив. Далее содержимое базового массива байтов отображается вручную в цикле for each
. После этого указатель файла устанавливается с помощью метода Seek()
в начало запоминающего потока, из которого затем вводятся данные с помощью объекта потока memrdr
.
Запоминающие потоки очень полезны для программирования. С их помощью можно, например, организовать сложный вывод с предварительным накоплением данных в массиве до тех пор, пока они не понадобятся. Этот прием особенно полезен для программирования в такой среде с графическим пользовательским интерфейсом, как Windows
. Кроме того, стандартный поток может быть переадресован из массива. Это может пригодиться, например, для подачи тестовой информации в программу.
Применение классов StringReader и StringWriter
Для выполнения операций ввода-вывода с запоминанием в некоторых приложениях в качестве базовой памяти иногда лучше использовать массив типа string, чем массив типа byte. Именно для таких случаев и предусмотрены классы StringReader
и StringWriter
. В частности, класс StringReader
наследует от класса TextReader
, а класс StringWriter
— от класса TextWriter
. Следовательно, они представляют собой потоки, имеющие доступ к методам, определенным в этих двух базовых классах, что позволяет, например, вызывать метод ReadLine()
для объекта класса StringReader
, а метод WriteLine()
— для объекта класса StringWriter
.
Ниже приведен конструктор класса StringReader
:
StringReader(string s)
где s обозначает символьную строку, из которой производится чтение.
В классе StringWriter
определено несколько конструкторов. Ниже представлен один из наиболее часто используемых.
StringWriter()
Этот конструктор создает записывающий поток, который помещает выводимые данные в строку. Для получения содержимого этой строки достаточно вызвать метод ToString()
.
Ниже приведен пример, демонстрирующий применение классов StringReader
и StringWriter
.
// Продемонстрировать применение классов StringReader и StringWriter.
using System; using
System.IO;
class StrRdrWtrDemo {
static void Main() {