C# 4.0 полное руководство - 2011 - Герберт Шилдт
Шрифт:
Интервал:
Закладка:
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)
где s обозначает символьную строку, из которой производится чтение.
В классе StringWriter определено несколько конструкторов. Ниже представлен один из наиболее часто используемых.
StringWriter()
Этот конструктор создает записывающий поток, который помещает выводимые данные в строку. Для получения содержимого этой строки достаточно вызвать метод ToString().
Ниже приведен пример, демонстрирующий применение классов StringReader и StringWriter.
// // Продемонстрировать применение классов StringReader и StringWriter.
using System; using System.10;
class StrRdrWtrDemo { static void Main() {
StringWriter strwtr = null;
StringReader strrdr = null;
try {
// Создать объект класса StringWriter. strwtr = new StringWriter();
// Вывести данные в записывающий поток типа StringWriter. for (int i=0; i < 10; i++)
strwtr.WriteLine("Значение i равно: " + i);
// Создать объект класса StringReader. strrdr = new StringReader(strwtr.ToString());
//А теперь ввести данные из считывающего потока типа StringReader. string str = strrdr.ReadLine(); while(str != null) {
str = strrdr.ReadLine();
Console.WriteLine(str);
}
} catch(IOException exc) {
Console.WriteLine("Ошибка ввода-выводап" + exc.Message);
} finally {
// Освободить ресурсы считывающего и записывающего потоков, if(strrdr != null) strrdr.Close(); if(strwtr != null) strwtr.Close ();
}
}
}
Вот к каком результату приводит выполнение этого кода.
Значение i равно: 1 Значение i равно: 2 Значение i равно: 3 Значение i равно: 4 Значение i равно: 5 Значение i равно: 6 Значение i равно: 7 Значение i равно: 8 Значение i равно: 9
В данном примере сначала создается объект strwtr класса StringWriter,B который выводятся данные с помощью метода WriteLine(). Затем создается объект класса StringReader с использованием символьной строки, содержащейся в объекте strwtr. Эта строка получается в результате вызова метода ToString () для объекта strwtr. И наконец, содержимое данной строки считывается с помощью метода ReadLine ().
Класс File
В среде .NET Framework определен класс File, который может оказаться полезным для работы с файлами, поскольку он содержит несколько статических методов, выполняющих типичные операции над файлами. В частности, в классе File имеются методы для копирования и перемещения, шифрования и расшифровывания, удаления файлов, а также для получения и задания информации о файлах, включая сведения об их существовании, времени создания, последнего доступа и различные атрибуты файлов (только для чтения, скрытых и пр.). Кроме того, в классе File имеется ряд удобных методов для чтения из файлов и записи в них, открытия файла и получения ссылки типа FileStream на него. В классе File содержится слишком много методов для подробного их рассмотрения, поэтому мы уделим внимание только трем из них. Сначала будет представлен метод Сору (), а затем — методы Exists () и GetLastAccessTime (). На примере этих методов вы сможете получить ясное представление о том, насколько удобны методы, доступные в классе File. И тогда вам станет ясно, что класс File определенно заслуживает более тщательного изучения.
СОВЕТ
Ряд методов для работы с файлами определен также в классе Filelnfo. Этот класс отличается от класса File одним, очень важным преимуществом: для операций над файлами он предоставляет методы экземпляра и свойства, а не статические методы. Поэтому для выполнения нескольких операций над одним и тем же файлом лучше воспользоваться классом Filelnfo.
Копирование файлов с помощью метода Сору ()
Ранее в этой главе демонстрировался пример программы, в которой файл копировался вручную путем чтения байтов из одного файла и записи в другой. И хотя задача копирования файлов не представляет особых трудностей, ее можно полностью автоматизировать с помощью метода Сору (), определенного в классе File. Ниже представлены две формы его объявления.