лр1-8. Н и я классов
Скачать 5.95 Mb.
|
Доступ к физическим файлам можно получать и через статические методы класса File. Большинство методов объекта FileInfo представляют в этом смысле зеркальное отражение методов объекта File. 3.4 Потоки в системе ввода-вывода. Программы на языке C# выполняют операции ввода-вывода посредством потоков, которые построены на иерархии классов. Поток (stream) – это абстракция, которая генерирует и принимает данные. С помощью потока можно читать данные из различных источников (клавиатура, файл, память) и записывать в различные источники (принтер, экран, файл, память). Центральную часть потоковой системы С# занимает класс Stream пространства имен System.IO. Класс Stream представляет байтовый поток и является базовым для всех остальных потоковых классов. Производными от класса Stream являются классы потоков: 1. FileStream – байтовый поток, разработанный для файлового ввода-вывода. 130 2. BufferedStream – заключает в оболочку байтовый поток и добавляет буферизацию, которая во многих случаях увеличивает производительность программы. 3. MemoryStream – байтовый поток, который использует память для хранения данных. Программист может реализовать собственные потоковые классы. Однако для подавляющего большинства приложений достаточно встроенных потоков. 3.4.1 Байтовый поток. Чтобы создать байтовый поток, связанный с файлом, создается объект класса FileStream. При этом в классе определено несколько конструкторов. Чаще всего используется конструктор, который открывает поток для чтения и (или) записи: Параметр path определяет имя файла, с которым будет связан поток ввода-вывода данных. Параметр mode определяет режим открытия файла, который может принимать одно из возможных значений, определенных перечислением FileMode: – FileMode.Append – предназначен для добавления данных в конец файла; – FileMode.Create – предназначен для создания нового файла, при этом если существует файл с таким же именем, то он будет предварительно удален; – FileMode.CreateNew – предназначен для создания нового файла, при этом файл с таким же именем не должен существовать; – FileMоde.Open – предназначен для открытия существующего файла; – FileMode.ОpenOrCreate – если файл существует, то открывает его, в противном случае создает новый; – FileMode.Truncate – открывает существующий файл, но усекает его длину до нуля. Если попытка открыть файл оказалась неудачной, то генерируется одно из исключений: 131 – FileNotFoundException – файл невозможно открыть по причине его отсутствия; – IOException – файл невозможно открыть из-за ошибки ввода-вывода; – ArgumentNullException – имя файла представляет собой null-значение; – ArgumentException – некорректен параметр mode; – SecurityException – пользователь не обладает правами доступа; – DirectoryNotFoundException – некорректно задан каталог. Другая версия конструктора позволяет ограничить доступ только чтением или только записью: Параметры path и mode имеют то же назначение, что и в предыдущей версии конструктора. Параметр access, определяет способ доступа к файлу и может принимать одно из значений, определенных перечислением FileAccess: – FileAccess.Read – только чтение; – FileAccess.Write – только запись; – FileAccess.ReadWrite – и чтение, и запись. После установления связи байтового потока с физическим файлом внутренний указатель потока устанавливается на начальный байт файла. Для чтения очередного байта из потока, связанного с физическим файлом, используется метод ReadByte( ). После прочтения очередного байта внутренний указатель перемещается на следующий байт файла. Если достигнут конец файла, то метод ReadByte( ) возвращает значение -1. Для побайтовой записи данных в поток используется метод WriteByte( ). По завершении работы с файлом его необходимо закрыть. Для этого достаточно вызвать метод Close( ). При закрытии файла освобождаются системные ресурсы, ранее выделенные для этого файла, что дает возможность использовать их для работы с другими файлами. 132 В данном примере создаются два потока fileIn (для чтения байтов из файла в поток) и fileOut (для записи байтов из потока в файл). Каждый из потоков ассоциируется со своим файлом. Затем в цикле производится побайтовое чтение файла «ФайлСТекстом.txt» до момента, когда функция ReadByte( ) вернет значение -1 (то есть достигнут конец файла). При этом на каждой итерации цикла считывается один байт и на этой же итерации этот байт записывается в файл «ФайлКопия.txt». После всех операция оба потока закрываются. Весь код, осуществляющий работу с файлами заключен в конструкцию try … catch. Это позволяет повысить устойчивость программы к ошибкам. 3.4.2 Символьный поток. 133 Чтобы создать символьный поток нужно поместить объект класса Stream (например FileStream) внутрь объекта класса StreamWriter или объекта класса StreamReader. В этом случае байтовый поток будет автоматически преобразовываться в символьный. Класс StreamWriter предназначен для организации выходного символьного потока. В нем определено несколько конструкторов. Один из них записывается следующим образом: Параметр stream определяет имя уже открытого байтового потока. Этот конструктор генерирует исключение типа ArgumentException, если поток stream не открыт для вывода, и исключение типа ArgumentNullException, если он (поток) имеет null-значение. Другой вид конструктора позволяет открыть поток сразу через обращения к файлу: Параметр path определяет имя открываемого файла. Например, создать экземпляр класса StreamWriter можно следующим образом: И еще один вариант конструктора StreamWriter: Параметр path определяет имя открываемого файла, а параметр append может принимать значение true – если нужно добавлять данные в конец файла, или false – если файл необходимо перезаписать. Например: 134 Объявив таким образом переменную fileOut_1 для записи данных в поток можно обратиться к методу WriteLine: В данном случае для записи используется метод, аналогичный статическому методу класса Console. Это действительно схожие механизмы ввода-вывода. Класс StreamReader предназначен для организации входного символьного потока. Один из его конструкторов выглядит следующим образом: Параметр stream определяет имя уже открытого байтового потока. Этот конструктор генерирует исключение типа ArgumentException, если поток stream не открыт для ввода. Создать экземпляр класса StreamReader можно следующим образом: Как и в случае с классом StreamWriter у класса StreamReader есть и другой вид конструктора, который позволяет открыть файл напрямую: Параметр path определяет имя открываемого файла. Обратиться к данному конструктору можно следующим образом: В C# символы реализуются кодировкой Unicode. Для того, чтобы можно было обрабатывать текстовые файлы, содержащие русские символы, созданные, например, в Блокноте, рекомендуется вызывать следующий вид конструктора StreamReader: 135 Параметр Encoding.GetEncoding(1251) говорит о том, что будет выполняться преобразование из кода Windows-1251 (одна из модификаций кода ASCII, содержащая русские символы) в Unicode. Тип Encoding реализован в пространстве имен System.Text. Для чтения данных из потока fileIn можно воспользоваться методом ReadLine. При этом если будет достигнут конец файла, то метод ReadLine вернет значение null. Рассмотрим пример, в котором данные из одного файла копируются в другой, но уже с использованием классов StreamWriter и StreamReader. В данном примере осуществляется копирование содержимого одного символьного файла в другой. Таким образом, данный способ копирования одного файла в другой, дает тот же результат, что и при использовании байтовых потоков. Однако, его работа будет менее эффективной, т.к. будет тратиться дополнительное время на преобразование байтов в символы. У символьных потоков есть и свои преимущества. Например, можно использовать регулярные выражения для поиска заданных фрагментов текста в файле. 136 3.4.3 Перенаправление стандартных потоков. Тремя стандартными потоками, доступ к которым осуществляется через свойства Console.Out, Console.In и Console.Error, могут пользоваться все программы, работающие в пространстве имен System. Свойство Console.Out относится к стандартному выходному потоку. По умолчанию это консоль. Например, при вызове метода Console.WriteLine() информация автоматически передается в поток Console.Out. Свойство Console.In относится к стандартному входному потоку, источником которого по умолчанию является клавиатура. Например, при вводе данных с клавиатуры информация автоматически передается потоку Console.In, к которому можно обратиться с помощью метода Console.ReadLine(). Свойство Console.Error относится к ошибкам в стандартном потоке, источником которого также по умолчанию является консоль. Однако эти потоки могут быть перенаправлены на любое совместимое устройство ввода-вывода, например, на работу с физическими файлами. Перенаправить стандартный поток можно с помощью методов SetIn(), SetOut() и SetError(), которые являются членами класса Console: Пример перенаправления потоков представлен в следующей программе, демонстрирующей, что стандартный поток вывода перенаправляется в один файл, а поток ввода – в другой: 137 4. Оборудование и материалы Для выполнения лабораторной работы рекомендуется использовать персональный компьютер со следующими характеристиками: 64-разрядный (x64) процессор с тактовой частотой 1 ГГц и выше, оперативная память – 1 Гб и выше, свободное дисковое пространство – не менее 1 Гб, графическое устройство DirectX 9. Программное обеспечение: операционная система WINDOWS 7 и выше, Microsoft Visual Studio 2012 и выше. 138 5. Указания по технике безопасности Техника безопасности при выполнении лабораторной работы определяется общепринятой для пользователей персональных компьютеров. Самостоятельно не производить ремонт персонального компьютера, установку и удаление программного обеспечения; в случае неисправности персонального компьютера сообщить об этом обслуживающему персоналу лаборатории; не касаться электрических розеток металлическими предметами; рабочее место пользователя персонального компьютера должно содержаться в чистоте; не разрешается возле персонального компьютера принимать пищу, напитки. 6. Методика и порядок выполнения работы Для выполнения лабораторной работы необходимо спроектировать многомодульное приложение, использующее файлы для ввода и вывода информации. Например, требуется разработать приложение, которое позволяет: – генерировать матрицу случайных чисел с сохранением ее в файл; – считывать матрицу из файла; – выводить матрицу на экран. Для выполнения данного задания-примера достаточно в отдельном проекте реализовать класс. Этот проект следует скомпилировать в виде dll-файла. Затем, в основной программе просто необходимо использовать данную библиотеку. Класс библиотеки назовем Matrix. В нем определим следующие функции: 139 Рисунок 19.1 – Основные методы класса Matrix. Листинг метода GenegateMatrix: Рисунок 19.2 – Метод для создания матрицы заданного размера и заполнения ее случайными числами. Листинг метода SaveMatrix: 140 Рисунок 19.3 – Метод для сохранения матрицы в файл. Рисунок 19.4 – Метод загрузки матрицы из файла. 141 На рис. 19.4 представлен листинг метода LoadMatrix. Листинг метода PrintMatrix: Рисунок 19.5 – Метод для вывода матрицы. Основная программа для использования класса-матрицы представлена на рис. 19.6 Рисунок 19.6 – Работа с библиотечным классом. В результате работы данного кода будет создан файл FileForMatrix.txt следующего содержания: 142 Рисунок 19.7 – Результирующий файл. На экран будет выведена следующая информация: Рисунок 19.8 – Вывод программы в консоль. Выполните индивидуальное задание, согласно предложенному варианту. В каждом варианте необходимо спроектировать многомодульное приложение (оптимально 2 модуля). Исходные данные в каждом варианте программа получает из входного файла. 143 |