Міністерство освіти та науки України
НУ „Львівська політехніка”
Лекція №8
з курсу: «Застосування засобів об’єктно-орієнтованого програмування в лінгвістичних задачах»
Львів - 2010
Розділ 6. Файли
Програми, які до цього часу ми розглядали, виводили результат своєї
роботи на екран. Разом з тим, Delphi дозволяє зберігати результати роботи
програми на диску комп'ютера, у файлі, що дає можливість
використовувати ці дані для подальшої обробки.
6.1. Оголошення файлу
Файл — це структура даних що має ім’я, та містить послідовність
елементів даних одного типу, причому кількість елементів послідовності
практично не обмежена. У першому наближенні файл можна розглядати як
масив змінної довжини необмеженого розміру.
Як і будь-яка структура даних (змінна, масив) програми, файл повинен
бути оголошений в розділі опису змінних. При оголошенні файлу
указується тип елементів файлу.
У загальному вигляді оголошення файлу виглядає так:
Ім’я: file of Тип елементів;
Приклади:
res: file of char; // файл символів
koef: file of real; // файл дійсних чисел
f: file of integer; // файл цілих чисел
Файл, компонентами якого є дані символьного типу, називається
символьним, або текстовим. Опис текстового файлу в загальному вигляді
виглядає так:
Імя: textfile;
де:
.
ім'я — ім'я файлової змінної;
.
TextFile — позначення - типу, який вказує, що Ім'я — це файлова
змінна, яка представляє текстовий файл.
6.2. Призначення імені файлу
Оголошення файлової змінної задає тільки тип компонентів файлу. Для
того, щоб програма могла виводити дані у файл або прочитувати дані з
файлу, необхідно вказати конкретний файл, тобто пов'язати файлову
змінну з конкретним файлом (задати ім'я файлу).
Ім'я файлу задається викликом процедури AssignFile, що пов'язує
файлову змінну з конкретним файлом.
Опис процедури AssignFile виглядає наступним чином:
AssignFile(var f, Ім’я файла: string)
Ім'я файлу задається згідно прийнятим в Windows правилам. Воно
може бути повним, тобто складатися не тільки безпосередньо з імені
файлу, але і включати шлях до файлу (ім'я диска, каталогів і підкаталогів).
Нижче приведені приклади виклику процедури AssignFiie:
AssignFile(f, 'a:\result.txt');
AssignFile(f, '\students\ivanov\koreni.txt');
fname:=('otchet.txt'); AssignFile(f,fname);
6.3. Вивід у файл
Безпосередньо вивід в текстовий файл здійснюється за допомогою
інструкції write або writeln. У загальному вигляді ці інструкції записуються
таким чином:
write (Файлова змінна, Список виводу) ;
writeln (Файлова змінна, Список виводу);
де:
.
Файлова змінна — це змінна, що ідентифікує файл, в який
виконується вивід;
.
Список виводу – це розділені комами імена змінних, значення яких
треба вивести у файл. Окрім імен змінних в список виводу можна
включати стрічкові константи.
Наприклад, якщо змінна f є змінною типу TextFiie, то інструкція виводу
значень змінних x1 і х2 у файл може бути такій:
write(f, 'Корені рівняння', x1, х2);
Відмінність між інструкціями write і writeln полягає в тому, що
інструкція writeln після виведення всіх значень, вказаних в списку виводу,
записує у файл символ "новий рядок".
6.4. Відкриття файлу для виводу
Перед виводом у файл його необхідно відкрити. Якщо програма, що
формує вихідний файл, вже використовувалася, то можливо, що файл з
результатами роботи програми вже є на диску. Тому програміст повинен
вирішити, як поступити із старим файлом: замінити старі дані новими або
нові дані додати до старих. Спосіб використання старого варіанту
визначається під час відкриття файлу.
Можливі наступні режими відкриття файлу для запису в нього даних:
.
перезапис (запис нового файлу поверх того, що існує або створення
нового файлу);
.
додавання в існуючий файл.
Для того, щоб відкрити файл в режимі створення нового файлу або
заміни що існує, необхідно викликати процедуру Rewrite(f), де f —
файлова змінна типу TextFile.
Для того, щоб відкрити файл в режимі додавання до вже існуючих
даних, що знаходяться в цьому файлі, потрібно викликати процедуру
Append(f), де f — файлова змінна типу TextFile.
На мал. 6.1 приведено діалогове вікно програми, яка виконує запис
або додавання в текстовий файл.
Мал. 6.1. Діалогове вікно програми запису-додавання у файл
У лістингу 6.1 приведена процедура, яка запускається натисненням
командної кнопки Записати. Вона відкриває файл в режимі створення
нового або заміщення існуючого файлу і записує текст, що знаходиться в
полі компоненту Memo1.
Ім'я файлу потрібно ввести під час роботи в полі Edit1. Можна задати
зумовлене ім'я файлу під час розробки форми додатку. Для цього треба
привласнити значення, наприклад test.txt, властивості Edit1.Text.
Лістинг 6.1. Створення нового або заміщення існуючого файлу
procedure TForm1.Button1Click(Sender: TObject);
var
f: TextFile; // файл
fName: String[80]; // ім'я файлу
i: integer;
begin
fName := Edit1.Text;
AssignFile(f, fName);
Rewrite(f); // відкрити для перезапису
// запис у файл
for i: =0 to Memo1.Lines.Count do // рядки нумеруються з нуля
writeln(f, Memo1.Lines[i]);
CloseFile(f); // закрити файл
MessageDlg('Дані ЗАПИСАНІ у файл ',mtIlnformation,[mbOk],0);
end;
У лістингу 6.2 приведена процедура, яка запускається натисненням
командної кнопки Додати. Вона відкриває файл, ім'я якого вказане в полі
Edit1, і додає в нього вміст поля Memol.
Лістинг 6.2. Додавання в існуючий файл
procedure TForm1.Button2Click(Sender: TObject);
var
f: TextFile; // файл
fName: String[80];.// ім'я файлу
i: integer;
begin
fName := Edit1.Text;
AssignFile(f, fName);
Append(f); // відкрити для додавання
// запис у файл
for i:=0 to Memo1.Lines.Count do // рядки нумеруються з нуля
writeln(f, Memo1.Lines[i]);
CloseFile(f); // закрити файл
MessageDlg('Дані ДОДАНІ у файл ', mtInformation, [mbOk], 0);
end;
6.5. Помилки відкриття файлу
Спроба відкрити файл може завершитися невдачею і викликати
помилку часу виконання програми. Причин невдачі при відкритті файлів
може бути декілька. Наприклад, програма спробує відкрити файл на
гнучкому диску, який не готовий до роботи (не закрита шторка
накопичувача, або диск не вставлений в накопичувач). Інша причина —
відсутність файлу, що відкривається в режимі додавання (файлу немає —
додавати нeма куди).
При запуску програми з Delphi у разі помилки під час відкриття файлу
виникає виключення, і на екрані з'являється діалогове вікно з
повідомленням (мал. 6.2).
Мал. 6.2. Приклад повідомлення про помилку відкриття файлу (програма
запущена з Delphi)
Якщо програма запускається з Windows, то вікно з повідомленням про
помилку виглядає інакше (мал. 6.3).
Мал. 6.3. Приклад повідомлення про помилку відкриття файлу . (програма
запущена з Windows)
Програма може узяти на себе завдання контролю за результатом
виконання інструкції відкриття файлу. Зробити це можна, перевіривши
значення функції IOResult (input-Output Result — результат
введення/виводу). Функція IOResuit повертає 0, якщо операція
введення/виводу завершилася успішно; інакше — код помилки (не нуль).
Для того, щоб програма змогла перевірити результат виконання
операції введення/виводу, потрібно дозволити їй це робити. Для цього
треба перед інструкцією виклику процедури відкриття файлу помістити
директиву компілятору — рядок {$I-}, який забороняє автоматичну
обробку помилок введення/виводу. Ця директива повідомляє компілятор,
що програма бере на себе контроль помилок. Після інструкції відкриття
файлу слід помістити директиву {$I+}, поновлюючу режим автоматичної
обробки помилок введення/виводу.
На мал. 6.4 приведена блок-схема алгоритму відкриття файлу для
додавання, що забезпечує створення файлу (і що тим самим знімає
помилку, що виникає при спробі відкрити неіснуючий файл) у випадку,
якщо файлу, що відкривається для додавання, на диску ще немає.
Мал. 6.4. Алгоритм відкриття файлу з обробкою можливої помилки
Нижче приведений фрагмент програми, що реалізовує приведений
вище алгоритм відкриття файлу.
AssignFile(f,filename);
{$I-}
Append(f) // відкрити для додавання
{$I+}
if IOResult<> 0 // помилка відкриття
then Rewrite(f); // відкрити для запису
// відкрити існуючий або новий файл
6.6. Закриття файлу
Відкрити файл
в режимі додавання(Append)
Помилка?
ТакНіВідкрити файл
в режимі заміни(Rewrite) – створити
новий
Перед завершенням роботи програма повинна закрити всі відкриті
файли. Це робиться викликом процедури close. Процедура close має один
параметр — ім'я файлової змінної. Приклад використання процедури:
Close(f);
Приклад програми
Наступна програма веде просту базу даних. При кожному її запуску на
екрані з'являється діалогове вікно (мал. 7.5), в поля якого користувач
може ввести дату і температуру повітря.
Мал. 6.5. Діалогове вікно програми База даних "Погода"
Дата вводиться в поле Edit1, температура — в полі Edit2. Текст
програми приведений в лістингу 7.3.
Лістинг 6.3, Проста база даних (запис у файл)
unit pogoda_;
interface
uses
Windows, Messages, SysUtils, Variants, Classes
Graphics, Controls, Forms, Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit; // дата
Edit2: TEdit; // температура
Button1: TButton; // кнопка Додати
Label1: TLabe1;
Label2: TLabe1;
procedure FormActivate(Sender: TObject);
procedure ButtonlClick(Sender: TObject);
procedure FormClose(Sender: TObject;
var Action: TCloseAction); private
{ Private declarations } public
{ Public declarations } end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const
DBNAME = 'a:\pogoda. db';
var
db: TextFile; // файл — база даних
procedure TForm1.FormActivate(Sender: TObject);
begin
AssignFile(db, DBNAME);. {$I-}
Append(db); if IOResult = 0 then
begin
Edit1.Text := DateToStr(Date); // отримати поточну дату
Edit2.SetFocus; // курсор в полі Edit2
end
else begin
Rewrite(db);
if IOResult <> 0 then begin
// зробити недоступними поля введення // і командну кнопку
Edit1.Enabled := False; Edit2.Enabled := False;
Button1.Enabled := False;
ShowMessage('Помилка створення '+DBNAME);
end;
end;
end;
// клацання на кнопці Додати
procedure Tform1.Button1Click(Sender: TObject);
begin
if (Length(Edit1.text)=0) or (Length(Edit2.text)=0)
then ShowMessage('Помилка введення даних.' +#13+'Bce поля
повинні бути заповнені.')
else writeln(db, edit1.text', ',edit2.text);
end;
// Подія OnClose виникає при закритті форми
procedure TForm1.FormClose(Sender: TObject; var Action:
TCloseAction);
begin
CloseFile(db); // закрити файл БД
end;
end.
Файл бази даних відкриває процедура FormActivate, яка обробляє
подію onActivate. Подія OnActivate виникає у момент активізації форми,
тому процедура запускається автоматично, при активізації форми додатку.
Якщо операція відкриття файлу завершується успішно, то в полі Edit1
записується поточна дата. Інформація про поточну дату повертає функція
Date. Для перетворення повертаного функцією Date значення (числа типу
Double) в зручну для сприйняття форму використовується функція
Dateiostr. Після запису дати в полі Editi процедура обробки події onActivate
із застосуванням методу setFocus встановлює курсор в полі введення
температури. Якщо в процесі відкриття або створення нового файлу
виникає помилка, то процедура робить недоступною кнопку Додати і
виводить інформаційне повідомлення.
Процедура TForm1.Button1Click (процедура обробки події onclick)
запускається натисненням кнопки Додати (Button1). В результаті введена
інформація записується в базу даних — файл pogoda.db. Перед
виконанням запису програма перевіряє, чи всі поля форми заповнені, і,
якщо не все, то виводить інформаційне повідомлення.
В результаті роботи процедури в кінець файлу pogoda.db буде доданий
рядок, що містить дату (число, місяць, рік) і температуру.
У даній програмі використовується інструкція writein, а не write, для
того, щоб дані за кожен день розташовувалися в базі даних на окремому
рядку.
Звернете увагу, що список виведення інструкції writein складається з
трьох елементів. Після виводу у файл дати (Edit1.text) у файл записується
пропуск, а затем— температура (edit2.txt). Якщо температуру записати у
файл відразу після дати, то числа, відповідні року і температурі, зіллються
в одну послідовність цифр.
Закриває базу даних процедура TFormi.Formciose, яка обробляє подію
enclose, що виникає при закритті форми додатку.
Після декількох запусків програми файл pogoda.db можливо,
наприклад, таким:
9.05.2001 10 10.05.2001 12 11.05.2001 10 12.05.2001 7
6.7. Зчитування з файлу
Програма може вводити початкові дані не тільки з клавіатури, але і з
текстового файлу. Для того, щоб скористатися цією можливістю, потрібно
оголосити файлову змінну типу TextFile, призначити їй за допомогою
інструкції AssignFile ім'я файлу, з якого прочитуватимуться дані, відкрити
файл для читання (введення) і прочитати (ввести) дані, використовуючи
інструкцію read або readln.
Відкриття файлу
Відкриття файлу для введення (читання) виконується викликом
процедури Reset, що має один параметр — файлову змінну. Перед
викликом процедури Reset за допомогою функції AssignFile файлова
змінна повинна бути пов'язана з конкретним файлом.
Наприклад, наступні інструкції відкривають файл для введення:
AssignFile(f, 'c:\data.txt'); Reset(f);
Якщо ім'я файлу вказане невірно, наприклад файлу з вказаним ім'ям на
диску немає, то виникає помилка часу виконання програми. Слід
зазначити, що іншою причиною виникнення помилки при відкритті файлу,
що знаходиться на гнучкому диску, може бути відсутність готовності
дисковода, простіше кажучи, відсутність диска в накопичувачі.
Тому в програмі слід передбачити можливість повторної спроби
відкриття файлу після підтвердження повторення операції.
Як і при відкритті файлу для запису, програма може узяти на себе
завдання обробки можливої помилки при відкритті файлу, перевіряючи
значення функції IOResult.
Фрагмент програми, текст якого приведений в лістингу 6.4,
використовує значення функції lOResult для перевірки результату
відкриття файлу. Якщо спроба відкрити файл викликає помилку, то
програма виводить діалогове вікно з повідомленням про помилку і запитом
на підтвердження повторного відкриття файлу.
Лістинг 6.4. Обробка помилки відкриття файлу (фрагмент
програми)
var
fname : string[80]; // ім'я файлу
f : TextFile; // файл
res : integer; // код помилки відкриття файлу (значення lOResult)
answ : word; // відповідь користувача
begin
fname := 'a:\test.txt'; AssignFile (f, fname);
repeat
{$I-}
Reset(f); // відкрити файл для читання
{$I+}
res:=IOResult;
if res <> 0
then answ:=MessageDlg('Помилка відкриття '+ fname+#13 +'Повторити
спробу?',mtWarning, [mbYes, mbNo],0); until (res= 0) OR
(answ = mrNo);
if res <> 0
then exit; // завершення процедури
// тут інструкції, які виконуються
// у разі успішного відкриття файлу
end;
6.8. Читання даних з файлу
Читання з файлу виконується за допомогою інструкцій read і readln,
які в загальному вигляді записуються таким чином:
read( Файлова змінна, Список змінних);
readln( Файлова змінна, Список змінних);
де:
.
Файлова змінна — змінна типу TextFile;
.
Список змінних — імена змінних, розділені комами.
Зчитування чисел
Слід розуміти, що в текстовому файлі знаходяться не числа, а їх
зображення. Дія, що виконується інструкціями read або readln, фактично
складається з двох частин: спочатку з файлу читаються символи до появи
роздільника (пропуску або кінця рядка), потім прочитані символи, числа,
що є зображенням, перетворяться в число, і набутого значення
привласнюється змінною, ім'я якої вказане як параметр інструкції read або
readln.
Наприклад, якщо текстовий файл а:\data. txt містить наступні рядки:
23 15 45 28 56 71
то в результаті виконання інструкцій:
AssignFile(f, 'a:\data.txt');
Reset(f); // відкрити для читання
read(f, а); read(f, b, c); read(f, d);
значення змінних будуть наступними: а = 23, b = 15, з = 45, d = 28.
Відмінність інструкції readin від read полягає в тому, що після
прочитування з файлу чергового числа і привласнення набутого значення
змінній, ім'я якої стоїть останнім в списку параметрів інструкції readin,
покажчик читання з файлу автоматично переміщається в початок
наступного рядка файлу, навіть в тому випадку, якщо за прочитаним
числом є ще числа.
Тому в результаті виконання інструкцій
AssignFile(f,'a:\data.txt');
Reset(f);
readin(f, а);
readin(f, b, c);
readin(f, d);
значення змінних будуть наступними: а = 23, b = 45, з = 28, d = 56.
Якщо при читанні значення чисельної змінної у файлі замість
зображення числа буде якась інша послідовність символів, то відбудеться
помилка.
Зчитування стрічок
У програмі стрічкова змінна може бути оголошена з вказівкою довжини
або без неї.
Наприклад:
strichka1:string[10];
strichka2:string;
При читанні з файлу значення строкової змінної, довжина якої явно
задана в її оголошенні, прочитується стільки символів, скільки вказано в
оголошенні, але не більше, ніж в поточному рядку.
При читанні з файлу значення строкової змінної, довжина якої явно не
задана в оголошенні змінній, значенням змінної стає частина поточного
рядка, що залишилася після останнього читання. Іншими словами, якщо
треба прочитати з файлу весь рядок, то оголосите строкову змінну,
довжина якої свідомо більше щонайдовшого рядка файлу, і прочитуйте
рядки в цю змінну.
Якщо однією інструкцією readin здійснюється введення декілька,
наприклад, два змінних, то перша змінна міститиме стільки символів,
скільки вказано в її оголошенні або, якщо довжина не вказана, весь рядок
файлу. Друга змінна міститиме символи поточного рядка, що залишилися,
або, якщо таких символів немає, не міститиме жодного символу (довжина
рядка рівна нулю).
Хай, наприклад, текстовий файл f- reads.txt містить рядки:
Петрова Маша Васильев Антон Цой Лариса
У табл. 6.1 приведено декілька варіантів оголошення змінних,
інструкції читання з файлу freinds.txt і значення змінних після виконання
інструкцій читання.
Таблиця 6.1. Приклади читання рядків з файлу
Оголошення Інструкція
зчитування змінних з файлу
Значення змінних після
зчитування з файлу
fnam: string[15]
Readln (f, fnam, name)
fnam= ' Петрова’
name: string[10]
name= ' Маша
fnam, name: string;
Readln (f, fnam, name)
fam= ' Петрова Маша '
name= ' '
drug: string[80]
Readln (f, drug)
drug =' Петрова Маша'
6.9. Мітка кінця файлу
Хай на диску є деякий текстовий файл. Потрібно в діалогове вікно
вивести вміст цього файлу. Рішення задачі задоволене очевидно: треба
відкрити файл, прочитати перший рядок, потім другий, третій і так далі до
тих пір, поки не буде досягнутий кінець файлу. Але як визначити, що
прочитаний останній рядок, досягнутий кінець файлу?
Для визначення кінця файлу можна скористатися функцією EOF (End
of File — кінець файлу). У функції EOF один параметр — файлова змінна.
Значення функції EOF рівне False, якщо прочитаний елемент даних не є
останнім у файлі, тобто можливе подальше читання. Якщо прочитаний
елемент даних є останнім, то значення EOF рівне True.
Значення функції EOF можна перевірити відразу після відкриття
файлу. Якщо при цьому воно опиниться рівним True, то це означає, що
файл не містить жодного елементу даних, тобто є порожнім (розмір такого
файлу рівний нулю).
У лістингу 6.5 приведена процедура, яка виконує поставлене завдання.
Вона читає рядки з файлу, ім'я якого ввів користувач під час роботи
програми, і виводить ці рядки в полі Memo. Вікно програми приведене на
мал. 6.6.
Мал. 6.6. Вікно програми Зчитування з файлу
Лістинг 6.5. Читання з файлу
unit rd_;
interface
uses
Windows, Messages, SysUtils, Variants, Classes
Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons;
type
TForm1 = class(TForm)
Button2: TButton;
Edit1: TEdit;
Memo1: TMemo;
Button1: TButton;
procedure Button2Click(Sender: TObject);
procedure ButtonlClick(Sender: TObject); private
{ Private declarations ) public
{ Public declarations } end;
var
Form1: Tform1;
implementation
{$R *.dfm}
// клацання на кнопці Відкрити
procedure TForm1.Button1Click(Sender: TObject);
var
f: TextFile; // файл
fName: String[80]; // ім'я файлу
buf: String[80]; // буфер для читання з файлу
begin
fName := Edit1.Text; AssignFile(f, fName); {$!-}
Reset(f); // відкрити для читання {$I+}
if IOResult <> 0 then begin
MessageDlg('Помилка доступу до файлу ' + fName mtError,[mbOk],0);
exit;
end;
// читання з файлу
while not EOF(f) do begin
readln(f, buf); // прочитати рядок з файлу
Memo1.Lines.Add(buf); // додати рядок в полі Memo1
end;
CloseFile(f); // закрити файл
end;
// клацання на кнопці Зберегти — запис у файл
procedure Tform1.Button2Click(Sender: TObject);
var
f: TextFile; // файл
fName: String[80]; // ім'я файлу
i: integer/; begin
fName := Edit1.Text; AssignFile(f, fName);
Rewrite(f); // відкрити для перезапису
// запис у файл
for i:=0 to Memo1.Lines.Count do // рядки нумеруються з нуля
writeln(f, Memo1.Lines[i]);
CloseFile(f); // закрити файл
MessageDlg('Дані записані у файл ', mtlnformation,[mbOk],0);
end;
end.
Для організації обробки файлу використана інструкція циклу while,
яка забезпечує перевірку значення функції EOF перед кожним читанням, у
тому числі і перед першим.
Наявність кнопки Зберегти і відповідної нею процедури дозволяє
зберегти вміст поля Memo у файлі, тобто програма читання з файлу є
примітивний редактор тексту.
Додавання чергового прочитаного з файлу рядка в полі Memo
виконується застосуванням методу Add до властивості Lines.