
Лабораторная работа №13
Создание приложений Windows Forms
для работы с потоковыми файлами
ИНДИВИДУАЛЬНОЕ ЗАДАНИЕ НА РАЗРАБОТКУ ПРОЕКТА
Создать проект решения следующей задачи:
Записать в новый файл те строки исходного текстового файла, которые нельзя преобразовать в число.
ФОРМАЛИЗАЦИЯ ЗАДАЧИ
Из условия задания следует, что его выполнение распадается на следующие этапы:
открытие входного файла для чтения строк;
открытие выходного файла для записи строк;
чтение из входного файла очередной строки;
вывод очередной строки в соответствующий объект формы;
обработка очередной строки с использованием функций, разработанных в предыдущей лабораторной работе;
вывод результата обработки в выходной файл;
вывод результата обработки в соответствующий объект формы.
РАЗРАБОТКА ГРАФИЧЕСКОГО ИНТРФЕЙСА ПОЛЬЗОВАТЕЛЯ ПРИЛОЖЕНИЯ
Графический интерфейс проекта изображен на рис. 1. Форма содержит 12 объектов:
текстовое поле txtInpPath для отображения полного пути к входному файлу;
текстовое поле txtOutPath для отображения полного пути к входному файлу;
список lstInpFile для отображения строк входного файла;
список lstOutFile для отображения строк выходного файла
кнопку cmdOpenInpFile для перехода в окно диалога выбора входного файла;
кнопку cmdOpenOutFile для перехода в окно диалога выбора выходного файла;
кнопку cmdExec для запуска процедуры чтения и обработки входного файла;
кнопку cmdExit для выхода из приложения;
четыре надписи, комментирующие назначение текстовых полей и списков.
Имена объектов (кроме надписей Label) сформированы с использованием правил венгерской нотации.
В
таблице 2 приведены установленные при
конструировании свойства основных
объектов формы.
Рисунок 1 – Форма проекта
Тип объекта |
Класс объекта |
Свойство |
Значение свойства |
Текстовое поле |
TextBox |
Name |
txtInpPath |
Font |
Microsoft Sans Serif; 7,8pt |
||
TabStop |
False |
||
Enabled |
False |
||
Текстовое поле |
TextBox |
Name |
txtOutPath |
Font |
Microsoft Sans Serif; 7,8pt |
||
TabStop |
False |
||
Enabled |
False |
||
Список |
ListBox |
Name |
lstInpFile |
Font |
Microsoft Sans Serif; 7,8pt |
||
TabStop |
False |
||
ScrollAlwaysVisible |
True |
||
Список |
ListBox |
Name |
lstOutFile |
Font |
Microsoft Sans Serif; 7,8pt |
||
TabStop |
False |
||
ScrollAlwaysVisible |
True |
||
Кнопка |
Button |
Name |
cmdOpenInpFile |
Font |
Microsoft Sans Serif; 7,8pt |
||
Text |
Открытие входного файла |
||
TabIndex |
1 |
||
Кнопка |
Button |
Name |
cmdOpenOutFile |
Font |
Microsoft Sans Serif; 7,8pt |
||
Text |
Открытие выходного файла |
||
TabIndex |
2 |
||
Кнопка |
Button |
Name |
cmdExec |
Font |
Microsoft Sans Serif; 7,8pt |
||
Text |
Обработка файлов |
||
TabIndex |
3 |
||
Кнопка |
Button |
Name |
cmdExit |
Font |
Microsoft Sans Serif; 7,8pt |
||
Text |
Завершение работы |
||
TabIndex |
4 |
Таблица 1
Рисунок 2 – Схема алгоритма функции FileProc
РАЗРАБОТКА ПРОГРАММНОГО КОДА ПРИЛОЖЕНИЯ
Функции пользователя, служащие для обработки файлов, находятся в файле files.cpp. Функции, предназначенные для обработки отдельной строки, копируются из предыдущей лабораторной работы и здесь повторно не рассматриваются. На рисунке 3 приведен программный код функции FileProc, вызываемой из событийной процедуры.
Функция получает в качестве входных параметров указатели на входной и выходной потоки sr и sw, а также указатели на списки для отображения строк входного и выходного файлов lstInFile и lstOutFile.
Вначале объявляются и инициализируются пустыми строками строковые переменные InBuffer и OutBuffer – буферы для чтения и записи строк в файлы.
Затем организуется цикл while, в котором выполняется вся обработка файлов. В заголовке цикла производится чтение очередной строки входного файла в буфер InBuffer с помощью метода ReadLine. При достижении конца потока этот метод возвращает значение null, обеспечивая выход из цикла.
#include "stdafx.h"
void FileProc(StreamReader^ sr, StreamWriter^ sw, ListBox^ lstInFile, ListBox^ lstOutFile) { String^ InBuffer=""; try { while (InBuffer=sr->ReadLine()) { if (InBuffer->Length==0) continue; lstInFile->Items->Add(InBuffer); double out; if(!Double::TryParse(InBuffer, out)) { sw->WriteLine(InBuffer); lstOutFile->Items->Add(InBuffer); } } } catch (Exception^ ex) { MessageBox::Show(ex->Message, "Ошибка", MessageBoxButtons::OK, MessageBoxIcon::Error); } }
|
Рисунок 3 – Программный код функции FileProc
Пока цикл повторяется, выполняются следующие действия:
проверка прочитанной строки на непустое значение, в случае пустой строки пропуск ее и переход к следующей итерации с помощью оператора continue;
добавление прочитанной строки в список lstInFile формы;
вызов функции Find для получения слова – результата обработки входной строки и запись результата в буфер OutBuffer;
вывод содержимого буфера в выходной файл с помощью метода WriteLine;
добавление полученного слова в список lstOutFile формы.
В процессе повторения цикла возможны ошибки времени выполнения, для обработки которых использована конструкция try – catch.
Функция обработки файлов FileProc и вызываемые ею функции находятся в отдельном созданном файле files.cpp. Прототипы всех этих функций находятся в заголовочном файле files.h (рисунок 4). Доступ к пространству имен System::IO необходим для работы с файлами.
using namespace System; using namespace System::Windows::Forms; using namespace System::IO; void FileProc(StreamReader^, StreamWriter^, ListBox^, ListBox^);
|
Рисунок 4 – Текст заголовочного файла files.h
Событийные процедуры проекта приведены на рис 5, 6, 7, 9, 11.
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { lstInpFile->Items->Clear(); lstOutFile->Items->Clear(); txtInpPath->Clear(); txtOutPath->Clear(); cmdExec->Enabled=false; }
|
Рисунок 5 – Событийная процедура загрузки формы
В процедуре Form1_Load события загрузка формы очищаются списки формы и текстовые поля, а также делается недоступной кнопка Обработка файлов (она станет доступной только после открытия входного и выходного файлов).
private: System::Void cmdExit_Click(System::Object^ sender, System::EventArgs^ e) { this->Close(); }
|
Рисунок 6 – Событийная процедура кнопки Завершение работы
В процедуре cmdExit_Click события нажатие кнопки Завершение работы выполняется выход из приложения. Выход можно выполнить также закрытием окна с формой.
В событийной процедуре кнопки Открытие входного файла производится выбор текстового файла, созданного заранее в приложении Блокнот. Выбор производится с помощью стандартного диалога, создаваемого с использованием класса OpenFileDialog.
private: System::Void cmdOpenInpFile_Click(System::Object^ sender, System::EventArgs^ e) { OpenFileDialog^ openFileDialog = gcnew OpenFileDialog; openFileDialog->Title= "Открытие входного файла"; openFileDialog->InitialDirectory= "d:\\"; openFileDialog->Filter= "Текстовые файлы (*.txt)|*.txt"; openFileDialog->FilterIndex=1; openFileDialog->ShowReadOnly=true; openFileDialog->ReadOnlyChecked=true; openFileDialog->RestoreDirectory=true; if (openFileDialog->ShowDialog() == System::Windows::Forms::DialogResult::OK) txtInpPath->Text=openFileDialog->FileName; else txtInpPath->Text=""; cmdExec->Enabled=txtInpPath->Text->Length>0 && txtOutPath->Text->Length>0; }
|
Рисунок 7 – Событийная процедура кнопки Открытие входного файла
Вначале создается объект openFileDialog указанного класса. Затем определяются его свойства, и вызывается метод ShowDialog, выводящий на экран окно выбора файла (рисунок 8). Основные свойства и методы класса OpenFileDialog приведены в Приложении 1.
После выбора файла и нажатия кнопки Открыть (DialogResult::OK) полный путь к файлу (свойство FileName) отображается в текстовом поле формы txtInPath. При нажатии кнопки Отмена – это поле инициализируется пустой строкой.
В завершение устанавливается доступность кнопки Обработка файлов: она станет доступной только после выбора обоих файлов, входного и выходного.
Рисунок 8 – Окно выбора входного файла
private: System::Void cmdOpenOutFile_Click(System::Object^ sender, System::EventArgs^ e) { SaveFileDialog^ saveFileDialog = gcnew SaveFileDialog; saveFileDialog->Title= "Открытие выходного файла"; saveFileDialog->Filter= "Текстовые файлы (*.txt)|*.txt"; saveFileDialog->FilterIndex=1; saveFileDialog->OverwritePrompt=true;
if (saveFileDialog->ShowDialog() == System::Windows::Forms::DialogResult::OK) txtOutPath->Text=saveFileDialog->FileName; else txtOutPath->Text=""; cmdExec->Enabled=txtInpPath->Text->Length>0 && txtOutPath->Text->Length>0; }
|
Рисунок 9 – Событийная процедура кнопки Открытие выходного файла
В событийной процедуре кнопки Открытие выходного файла выполняется установка полного пути к текстовому файлу, в который будут выводиться результаты обработки строк входного файла. Установка производится с помощью стандартного диалога, создаваемого с использованием класса SaveFileDialog. Основные свойства и методы класса SaveFileDialog приведены в Приложении 1.
Метод ShowDialog класса SaveFileDialog выводит на экран окно, изображенное на рисунок 10. Следует выбрать папку для файла, в поле Имя файла ввести его имя (на данном рисунке – Слова) и нажать кнопку Сохранить. Установленный полный путь к файлу отображается в текстовом поле формы
txtOutPath.
Затем
снова устанавливается доступность
кнопки Обработка
файлов:
она станет доступной только после выбора
обоих файлов, входного и выходного.
Рисунок 10 – Окно установки пути к выходному файлу
Событийная процедура кнопки Обработка файлов подготавливает и запускает процесс обработки. Вначале очищаются списки формы, предназначенные для отображения содержимого обоих файлов: входного и выходного. Пути к файлам копируются из текстовых полей в строковые переменные InFile и OutFile.
Затем объявляются и инициализируются объекты sr и sw классов потокового ввода–вывода StreamReader и StreamWriter, соответственно. Основные свойства и методы этих классов приведены в Приложении 2.
Операторы создания потоков помещены в блок try, чтобы обработать возможные исключения при создании. При возникновении исключений выполняется блок catch, в котором выводится сообщение об ошибке, закрываются созданные потоки и производится выход из событийной процедуры.
При отсутствии ошибок вызывается пользовательская функция FileProc обработки файлов. В функцию передаются в качестве параметров созданные потоки и списки формы для вывода содержимого файлов. После завершения выполнения функции оба потока закрываются.
private: System::Void cmdExec_Click(System::Object^ sender, System::EventArgs^ e) { lstInpFile->Items->Clear(); lstOutFile->Items->Clear(); String^ InFile = txtInpPath->Text; String^ OutFile = txtOutPath->Text; StreamReader^ sr = nullptr; StreamWriter^ sw = nullptr; try { sr = gcnew StreamReader(InFile); sw = gcnew StreamWriter(OutFile, false); } catch (Exception^ ex) { MessageBox::Show(ex->Message, "Ошибка", MessageBoxButtons::OK, MessageBoxIcon::Error); if (sr) sr->Close(); if (sw) sw->Close(); return; } FileProc(sr, sw, lstInpFile, lstOutFile); sr->Close(); sw->Close(); }
|
Рисунок 11 – Событийная процедура кнопки Обработка файлов
Рисунок 12 – Результаты работы приложения
ДОКАЗАТЕЛЬСТВО ПРАВИЛЬНОСТИ РАБОТЫ
Правильность работы приложения подтверждается приведенными выше результатами его выполнения.