При выполнении этой программы получается следующий результат. Перзая буква: А Вторая буква: В Пятая буква: Е

Перзая буква: А Вторая буква: В Пятая буква: Е

Буквы алфавита, через одну:

АСЕ G‘I KMOQSUWY

Несмотря на то что метод Seek () имеет немало преимуществ при использовании с файлами, существует и другой способ установки текущего положения в файле с помощью свойства Position. Как следует из табл. 14.2, свойство Position доступно как для чтения, так и для записи. Поэтому с его помощью можно получить или же установить текущее положение в файле. В качестве примера ниже приведен фрагмент кода из предыдущей программы записи и чтения из файла с произвольным доступом random.dat, измененный с целью продемонстрировать применение свойства Position.

Console.WriteLine("Буквы алфавита через одну: "); for(int i=0; i < 26; i += 2) {

f.Position = i; // найти i-й символ посредством свойства Position ch = (char) f.ReadByte();

Console.Write(ch + " ");

}

Применение класса MemoryStream

Иногда оказывается полезно читать вводимые данные из массива или записывать выводимые данные в массив, а не вводить их непосредственно из устройства или выводить прямо на него. Для этой цели служит класс MemoryStream. Он представляет собой реализацию класса Stream, в которой массив байтов используется для ввода и вывода. В классе MemoryStream определено несколько конструкторов. Ниже представлен один из них:

MemoryStream(byte[ ] buffer)

где buffer обозначает массив байтов, используемый в качестве источника или адресата в запросах ввода-вывода. Используя этот конструктор, следует иметь в виду, что массив buffer должен быть достаточно большим для хранения направляемых в него данных.

В качестве примера ниже приведена программа, демонстрирующая применение класса MemoryStream в операциях ввода-вывода.

// Продемонстрировать применение класса MemoryStream.

Using System; using System.10;

class MemStrDemo { static void Main() {

byte[] storage = new byte[255];

// Создать запоминающий поток.

MemoryStream memsttm = new MemoryStream(storage);

// чтения и записи данных в потоки.

StreamWriter memwtr = new StreamWriter(memstrm);

StreamReader memrdr = new StreamReader(memstrm);

try {

// Записать данные в память, используя объект memwtr. for(int i=0; i < 10; i++)

memwtr.WriteLine("byte [" + i + "]: " + i);

// Поставить в конце точку, memwtr.WriteLine(".");

Memwtr.Flush() ;

Console.WriteLine("Чтение прямо из массива storage: ");

// Отобразить содержимое массива storage непосредственно. foreach(char ch in storage) { if (ch == '.') break;

Console.Write(ch);

}

Console.WriteLine("ХпЧтение из потока с помощью объекта 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 )

Наши рекомендации