Лабораторная работа №6. Лабораторная работа 6 Разработка программ с использованием файлов
Скачать 80.5 Kb.
|
Лабораторная работа №6Разработка программ с использованием файлов1. Цель работыОсвоение процесса разработки программ с использованием файлов на языке C#. 2. Задание на лабораторную работуРазработать программу согласно варианту задания, с использованием функций чтения и записи в текстовый файл. 3. Требования к программеПрограмма должна быть разработана в соответствии с вариантом задания (п. 7). Входные данные должны браться из текстового файла (input.txt), результат должен быть записан в выходной текстовый файл (output.txt). 4. Порядок выполнения работы1. Получить вариант задания (п. 7, таблица 7.1). 2. Изучить функции, используемые для работы с файлами, и необходимые для выполнения данной лабораторной работы (п. 5). 3. Разработать алгоритм подготовки и обработки данных на основе заданных операций. 4. Подготовить текст программы и отладить программу с использованием среды Visual Studio; см. пример п. 7.6. 5. Ответить на контрольные вопросы (п. 7.9). 6. Оформить отчет (см. п. 1.10). 5. Справки по файловым функциямФайл – это набор данных, который хранится на внешнем запоминающем устройстве (например на жестком диске). Файл имеет имя и расширение. Расширение позволяет идентифицировать, какие данные и в каком формате хранятся в файле. Под работой с файлами подразумевается: - cоздание файлов; - удаление файлов; - чтение данных; - запись данных; - изменение параметров файла (имя, расширение…); - другое. В Си-шарп есть пространство имен System.IO, в котором реализованы все необходимые нам классы для работы с файлами. Чтобы подключить это пространство имен, необходимо в самом начале программы добавить строку using System.IO. Для использования кодировок еще добавим пространство using System.Text; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; Непотоковый файловый ввод-выводПредоставляется статическим классом File. Этот класс не является наследником потоковых классов. Для создания пустого файла, в классе File есть метод Create(). Он принимает один аргумент – путь. Ниже приведен пример создания пустого текстового файла new_file.txt на диске D: static void Main(string[] args) { File.Create("D:\\new_file.txt"); } Если файл с таким именем уже существует, он будет переписан на новый пустой файл. Метод WriteAllText() создает новый файл (если такого нет), либо открывает существующий и записывает текст, заменяя всё, что было в файле: static void Main(string[] args) { File.WriteAllText("D:\\new_file.txt", "текст"); } Метод AppendAllText() работает, как и метод WriteAllText() за исключением того, что новый текст дописывается в конец файла, а не переписывает всё что было в файле: static void Main(string[] args) { File.AppendAllText("D:\\new_file.txt", "текст метода AppendAllText ()"); //допишет текст в конец файла } Метод Delete() удаляет файл по указаному пути: static void Main(string[] args) { File.Delete("d:\\test.txt"); //удаление файла } Пример использования методов WriteAllLines, ReadAllLines, AppendAllText и Exists: class Program { static void Main(string[] args) { string path = @"c:\temp\MyTest.txt"; // Текст добавляется в файл только один раз if (!File.Exists(path)) { // Создать файл и записать строки. Закрыть файл. string[] createText = { "Hello", "And", "Welcome" }; File.WriteAllLines(path, createText); } // Этот текст будет добавляться при каждом запуске программы string appendText = "This is extra text" + Environment.NewLine; File.AppendAllText(path, appendText); // Открыть файл, прочитать и закрыть. string[] readText = File.ReadAllLines(path); foreach (string s in readText) { Console.WriteLine(s); } } } Потоковый файловый ввод-выводЧтобы читать/записывать данные в файл на С# можно использовать потоки. Поток – это абстрактное представление данных (в байтах), которое облегчает работу с ними. В качестве источника данных может быть файл, устройство ввода-вывода, принтер. Класс Stream является абстрактным базовым классом для всех потоковых классов в Си-шарп. Для работы с файлами нам понадобится класс FileStream (файловый поток). FileStream - представляет поток, который позволяет выполнять операции чтения/записи в файл. static void Main(string[] args) { FileStream file = new FileStream("d:\\test.txt", FileMode.Open, FileAccess.Read); //открывает файл только на чтение } Режимы открытия FileMode: - Append – открывает файл (если существует) и переводит указатель в конец файла (данные будут дописываться в конец), или создает новый файл. Данный режим возможен только при режиме доступа FileAccess.Write. - Create - создает новый файл(если существует – заменяет) - CreateNew – создает новый файл (если существует – генерируется исключение) - Open - открывает файл (если не существует – генерируется исключение) - OpenOrCreate – открывает файл, либо создает новый, если его не существует - Truncate – открывает файл, но все данные внутри файла затирает (если файла не существует – генерируется исключение) static void Main(string[] args) { FileStream file1 = new FileStream("d:\\file1.txt", FileMode.CreateNew); //создание нового файла FileStream file2 = new FileStream("d:\\file2.txt", FileMode.Open); //открытие существующего файла FileStream file3 = new FileStream("d:\\file3.txt", FileMode.Append); //открытие файла на дозапись в конец файла } Режим доступа FileAccess: - Read – открытие файла только на чтение. При попытке записи генерируется исключение - Write - открытие файла только на запись. При попытке чтения генерируется исключение - ReadWrite - открытие файла на чтение и запись. Чтение из файла Для чтения данных из потока нам понадобится класс StreamReader. В нем реализовано множество методов для удобного считывания данных. Ниже приведена программа, которая выводит содержимое файла на экран: static void Main(string[] args) { FileStream file1 = new FileStream("d:\\test.txt", FileMode.Open); //создаем файловый поток StreamReader reader = new StreamReader(file1); // создаем «потоковый читатель» и связываем его с файловым потоком Console.WriteLine(reader.ReadToEnd()); //считываем все данные с потока и выводим на экран reader.Close(); //закрываем поток Console.ReadLine(); } Метод ReadToEnd() считывает все данные из файла. ReadLine() – считывает одну строку (указатель потока при этом переходит на новую строку, и при следующем вызове метода будет считана следующая строка).Свойство EndOfStream указывает, находится ли текущая позиция в потоке в конце потока (достигнут ли конец файла). Возвращает true или false. Запись в файл Для записи данных в поток используется класс StreamWriter. Пример записи в файл: static void Main(string[] args) { FileStream file1 = new FileStream("d:\\test.txt", FileMode.Create); //создаем файловый поток StreamWriter writer = new StreamWriter(file1); //создаем «потоковый писатель» и связываем его с файловым потоком writer.Write("текст"); //записываем в файл writer.Close(); //закрываем поток. Не закрыв поток, в файл ничего не запишется } Метод WriteLine() записывает в файл построчно (то же самое, что и простая запись с помощью Write(), только в конце добавляется новая строка). Нужно всегда помнить, что после работы с потоком, его нужно закрыть (освободить ресурсы), использовав метод Close(). 6. Процедуры и функции – методы классаПервыми формами модульности, появившимися в языках программирования, были процедуры и функции. Поскольку функции в математике использовались издавна, то появление их в языках программирования было совершенно естественным. Уже с первых шагов программирования процедуры и функции позволяли решать одну из важнейших задач, стоящих перед программистами, – задачу повторного использования программного кода. Один раз написанную функцию можно многократно вызывать в программе с разными значениями параметров, передаваемых функции в момент вызова. Встроенные в язык функции позволяли существенно расширить возможности языка программирования. Важным шагом в автоматизации программирования было появление библиотек процедур и функций, доступных из языка программирования. Долгое время процедуры и функции играли не только функциональную, но и архитектурную роль. Весьма популярным при построении программных систем был метод функциональной декомпозиции «сверху вниз», и сегодня еще играющий важную роль. Вся программа рассматривалась, как некоторая главная функция. В процессе проектирования программы происходила декомпозиция главной функции на подфункции, решающие частные задачи. Этот процесс декомпозиции продолжался до тех пор, пока не приходили к достаточно простым функциям, реализация которых не требовала декомпозиции и могла быть описана базовыми конструкциями языка программирования. с появлением ООП архитектурная роль функциональных модулей отошла на второй план. Для ОО-языков, к которым относится и язык C#, роль архитектурного модуля играет класс. Программная система строится из модулей, роль которых играют классы, но каждый из этих модулей имеют содержательную начинку, задавая некоторую абстракцию данных. Процедуры и функции связываются теперь с классом, они обеспечивают требуемую функциональность класса и называются методами класса. Поскольку класс в объектно-ориентированном программировании рассматривается как некоторый тип данных, то главную роль в классе начинают играть его данные – поля класса, задающие свойства объектов класса. Методы класса «служат» данным, занимаясь их обработкой. Помните, в C# процедуры и функции существуют только как методы некоторого класса, они не существуют вне класса. В данном контексте понятие класс распространяется и на все его частные случаи – структуры, интерфейсы, делегаты. В языке C# нет специальных ключевых слов – method, procedure, function, но сами понятия конечно же присутствуют. Синтаксис объявления метода позволяет однозначно определить, чем является метод – процедурой или функцией. Прежнюю роль библиотек процедур и функций теперь играют библиотеки классов. Библиотека классов FCL, доступная в языке C#, существенно расширяет возможности языка. Знание классов этой библиотеки, методов этих классов совершенно необходимо для практического программирования на C#, использование всей его мощи. Процедуры и функции. ОтличияФункция отличается от процедуры двумя особенностями: всегда вычисляет некоторое значение, возвращаемое в качестве результата функции; вызывается в выражениях. Процедура C# имеет свои особенности: возвращает формальный результат void, указывающий на отсутствие результата, возвращаемого при вызове процедуры; вызов процедуры является оператором языка; имеет входные и выходные аргументы, причем выходных аргументов – ее результатов – может быть достаточно много. Хорошо известно, что одновременное существование в языке процедур и функций в каком-то смысле избыточно. Добавив еще один выходной аргумент любую функцию можно записать в виде процедуры. Справедливо и обратное. Если допускать функции с побочным эффектом, то любую процедуру можно записать в виде функции. В языке С – дедушке C# – так и сделали, оставив только функции. Однако значительно удобнее иметь обе формы реализации метода – процедуры и функции. Обычно метод предпочитают реализовать в виде функции тогда, когда он имеет один выходной аргумент, рассматриваемый как результат вычисления значения функции. Возможность вызова функций в выражениях также влияет на выбор в пользу реализации метода в виде функции. В других случаях метод реализуют в виде процедуры. Описание методов (процедур и функций). СинтаксисСинтаксически в описании метода различают две части – описание заголовка и описание тела метода: заголовок_метода тело_метода Рассмотрим синтаксис заголовка метода: [атрибуты][модификаторы]{void| тип_результата_функции} имя_метода([список_формальных_аргументов]) Пример: public static int factorial (int n){ return (n == 1 ? n : n * factorial(n - 1)); } Имя метода и список формальных аргументов составляют сигнатуру метода. Заметьте, в сигнатуру не входят имена формальных аргументов, здесь важны типы аргументов. В сигнатуру не входит и тип возвращаемого результата. Квадратные скобки (метасимволы синтаксической формулы) показывают, что атрибуты и модификаторы могут быть опущены при описании метода. Обязательным при описании заголовка является указание типа результата, имени метода и круглых скобок, наличие которых необходимо и в том случае, если сам список формальных аргументов отсутствует. Формально тип результата метода указывается всегда, но значение void однозначно определяет, что метод реализуется процедурой. Тип результата, отличный от void, указывает на функцию. Вот несколько простейших примеров описания методов: void A() {…}; int B(){…); public void C(){…}; Пример использования вызова функции в программеnamespace ConsoleApplication3 { class Program { static int factorial (int n){ return (n == 1 ? n : n * factorial(n - 1)); } static void Main(string[] args) { int i = factorial(10); Console.WriteLine("Факториал числа 10 = " + i); Console.ReadKey(); } } } 7. Общее задание Создать файл input.txt. В нем задать строку произвольной длины. В основной программе необходимо считать данные из файла, выполнить преобразования и вычисления согласно варианту и записать полученный результат в файл output.txt. Варианты: Преобразовать строку символов, заменив в ней каждую из групп стоящих рядом точек одной точкой. Преобразовать строку символов, заменив в ней каждую из групп стоящих рядом точек многоточием ( т. е. тремя точками). Выяснить, имеются ли в строке S такие символы Si и Si+1, что Si - это запятая, а Si+1 - тире. Получить первое натуральное i, для которого каждый из символов Si и Si+1 совпадает с буквой А. Если такой пары символов в строке S нет, то ответом должно быть число 0. Известно, что среди символов строки S есть по крайней мере одна запятая. Найти такое натуральное i, что Si - первая по порядку запятая. Известно, что среди символов строки есть по крайней мере одна запятая. Найти такое натуральное i, что Si - последняя по порядку запятая. Выяснить, верно ли что среди символов строки имеются все буквы, входящие в слово ШАР. Выяснить, имеется ли среди символов строки пара соседствующих одинаковых символов. Выяснить, имеется ли среди символов строки пара соседствующих букв по или оп . Удалить из строки все группы букв вида abcd. Подсчитать наибольшее число идущих подряд пробелов. Выяснить, верно ли, что в строке имеются пять идущих подряд букв е. Преобразовать строку, удалив каждый символ * и повторив каждый символ, отличный от *. Определить число вхождений в строку группы букв abc. Заменить в этой строке каждую группу букв child группой букв children . 9. Контрольные вопросы1. Что такое «файл»? 2. Какую структуру может иметь имя файла? 3. Какие способы работы с файлами существуют в языке C#? 4. Каковы правила записи операторов чтения из файла и записи в файл? 5. Как происходит выполнение процедур чтения из файла (записи в файл)? 6. Как организовать обработку ошибок при работе с файлами? Каков алгоритм обработки? Какие операторы могут быть использованы для этого? 7. Что такое «текстовый файл»? Как определить в C#-программе файловые переменные для работы с текстовыми файлами? 8. Какие процедуры используются для открытия текстовых файлов, для чтения из файла, записи в файл? 9. Как организовать сохранение в файле данных, вводимых с клавиатуры? 10. Как организовать чтение данных из файла и вывод на экран? |