Робота з файлів в Дельфи h2>
Ця
стаття орієнтована на новачків, які бажають навчитися працювати з файлами в
Дельфі. У статті розглядаються стандартні I/O операції з файлами, типові
помилки та методи їх запобігання. p>
Intro p>
В
Дельфі файл представляється як іменована структура даних, тобто
послідовність однотипних даних. Грубо кажучи це величезний масив, число
елементів якого практично ні чим не обмежена. Для полегшення роботи з
файлами в Дельфи, кожен окремий файл представляє файлова змінна. Раз
вже це змінна, то вона повинна бути об'явлена як змінна. Однак про все
по порядку. p>
Step
by step p>
Step
1 - Обьявление файлової змінної p>
Файлова
мінлива в загальному вигляді оголошує у роздiлi var приблизно так: p>
F: file of Type; p>
Наприклад: p>
F:
File of integer; p>
Слід
помітити, що текстові файли оголошує трохи по іншому: p>
F
: TextFile; p>
Так
і взагалі текстові файли "особливі". Деякі функції працюють
тільки з текстовими файлами. Також можна оголосити не тільки файл цілих
чисел (integer), текстовий файл або файл будь-якого іншого типу, але і файл
власного типу або запису, помістивши оголошення типу або запису вище
оголошення файлової змінної. Наприклад: p>
type p>
TDay = (MON, TUE, WED, THU, FRI,
SAT, SUN); p>
var p>
F: File of TDay; p>
або: p>
type p>
TDay = record p>
Num: Integer; p>
Name: String [200]; p>
end; p>
var p>
F: File of TDay; p>
Слід
звернути увагу, що довжина строкових полів в записі повинна бути чітко
визначена (Name: String [200]) p>
Step
2 - Призначення і відкриття файлу p>
Після
оголошення файлової змінної потрібно пов'язати її з фізичним файлом на диску.
Зробити це можна за допомогою процедури AssignFile: p>
AssignFile (var
F: File; FileName: String); p>
Наприклад: p>
var F: TextFile; p>
... p>
begin p>
AssignFile (F, "text.txt "); p>
... p>
Після
виконання процедури файлова мінлива F буде пов'язана з файлом text.txt,
що знаходиться в папці з програмою. І всі дії, вироблені зі змінною
будуть діяти саме на цей файл. Однак змінну можна звільнити для
подальшого використання з іншим файлом процедурою CloseFile, але про це
нижче. Тепер необхідно відкрити файл, причому одним з декількох способів, в
Залежно від ваших потреб. Створити новий або перезаписати існуючий
можна за допомогою процедури Rewrite (F). Відкрити для запису в кінець файлу можна з
допомогою процедури Append (F). А відкриття файлу для читання здійснює процедура
Reset. P>
Step
3 - Стандартні I/O опреаціі з файлами p>
I/O
- Це операції введення/виводу (input/output). Тут ми розглянемо запис даних у
файл і читання цих даних. Спочатку запис. Записати у файл можна змінну або
константу того типу, якого було оголошено файл. Наприклад якщо файл був
оголошено отак F: File of Integer, то в нього можна буде записати дані тільки
типу Integer. При спробі записати дані іншого типу компілятор видасть
повідомлення про помилку. Запис у файл здійснюється процедурами Write ([var F:
File]; P1; [..., Pn]) і WriteLn ([var F: File]; P1; [..., Pn]). Друга відрізняється
від першого тим, що вона після запису параметра перемащает каретку на нову
рядок, тобто наступний параметр запишеться на новому рядку. Ось приклад
використання процедур: p>
var
F: TextFile; p>
Str
: String; p>
... p>
Str
: = "Some Text"; p>
WriteLn (F,
Str); p>
Write (F,
"це буде на новій стоці "); p>
write (F,
"а це на цій же рядку "); p>
... p>
Читання
даних відбувається благодоря процедур Read ([var F: File]; V1; [..., Vn]) і
ReadLn ([var F: File]; V1; [..., Vn]). Отлічіаются вони тим, що після прочитання
параметра процедурою ReadLn каретка переміщається на новий рядок, навіть якщо ще
були дані. Ось приклад: p>
var F: TextFile; p>
Str: String; p>
Str2: String; p>
Str3: String; p>
... p>
Read (F,
Str); p>
ReadLn (F,
Str2);// str2 буде містити дані, що йдуть після str p>
Read (F,
Str3);// str3 буде містити дані, що знаходяться на новій рядку після str2 p>
... p>
Думаю
не все так складно. p>
Step
4 - Закриття файлу p>
файлову
змінну після використання потрібно обьязательно звільнити, інакше програма
не закриється і буде видавати помилку. Також звільнення файлової змінної
буде корисно тоді, коли вам потрібно працювати з кількома файлами
послідовно, і після роботи з першим файлом можна звільнити змінну та
пов'язати її з новим файлом. Звільнення файлової перменной робить процедура
CloseFile (F: File). Примера я думаю не треба, тому що ніяких особливостей у неї
немає. p>
Приклад p>
Я
думаю новачкові буде все ж таки складно буде без прикладів розібратися в роботі з
файлами. Тому давайте розглянемо найпростіший приклад програми, яка за
натискання однієї кнопки буде запитувати ім'я файлу у користувача і записувати
вміст TMemo. А після натискання іншої кнопки програма знову ж таки буде
запитувати ім'я файлу, читати від туди записані дані і розміщати їх в TMemo.
Знаю, що запис і читання в TMemo можна організувати за допомогою спеціальних
методів. Але це всього лише приклад до статті. Вобщем кидайте на форму одну TMemo
і дві кнопки. Оброблювач першої кнопки приведіть до такого виду: p>
procedure
TForm1.Button1Click (Sender: TObject); p>
var p>
F: TextFile; p>
FileName: String; p>
i: Integer; p>
begin p>
FileName: = InputBox ( "Файл", "Введіть ім'я файлу", "default.txt "); p>
AssignFile (F, FileName); p>
Rewrite (F); p>
for i: = 0 to Memo1.Lines.Count do p>
WriteLn (F, Memo1.Lines [i ]); p>
CloseFile (F); p>
end; p>
Це
кнопка буде зберігати текстовий файл. Отже, в розділі var я оголосив три
локальні змінні: F типу TextFile це і є файлова змінна для
текстових файлів; FileName типу String буде служити для зберігання імені файлу;
І i типу Integer - для циклів. У першому рядку я шукаю у користувача ім'я
файлу. У другій я пов'язую файлову змінну з фізичним файлом на диску.
Рядок Rewrite (F) створює новий файл або перезаписує існуючий. ЧТо б
дані не змінювалися а додавалися в кінець файлу цей рядок потрібно замінити на
Append (F). Далі йде цикл з 0 до кількості всіх рядків Memo1. У циклі
вміст всі строк Memo1 по порядку записується у файл. Зверніть увагу,
що я використовую WriteLn для запису нової строчки. Якби я використав Write,
то всі рядки Memo1 у файлі перетворилися в одну. p>
Оброблювач
другий кнопки повинен виглядати приблизно так: p>
procedure
TForm1.Button2Click (Sender: TObject); p>
var p>
F: TextFile; p>
FileName, tmp: String; p>
begin p>
FileName: = InputBox ( "Файл", "Введіть ім'я файлу", "default.txt "); p>
AssignFile (F, FileName); p>
Reset (F); p>
while not EOF (f) do p>
begin p>
ReadLn (F, tmp); p>
Memo1.Lines.Add (tmp); p>
end; p>
CloseFile (F); p>
end; p>
Призначення
локальних змінних в цій процедурі аналогічні предудищім. Перша і друга
рядок аналогічні рядками з обробника першої кнопки. Reset (F) - це я
відкриваю файл для читання процедурою Reset. Далі запускається цикл по всьому
файлу (while not EOF (F) do). Функція EOF (F: File) повертає true коли
досягнуто кінець файлу. У циклі читається один рядок з файлу в змінну tmp
і додається в Memo1. От і все, думаю досить просто. Однак програму легко
обдурити і викликати виключення. Наприклад при читанні файлу користувач може
задати ім'я неіснуючого файлу. Тоді виникне помилка. Далі ми поговоримо про
способи захисту програми від винятків p>
Спосіб
1 - Найпростіший p>
Звичайно
найпростіший, але досить ефективний спосіб захисту можна організувати з
допомогою вкладених блоків try - except та try - finally. Ви знаєте, що якщо при
виконання інструкції в тілі блоку try - except відбувається виключення, то
виконання подальших інструкцій зупиняється і виконується те, що
знаходиться між except - end. Але якщо виникло виключення, а далі знаходиться
CloseFile (F), то ця процедура не виконується і програма не зможе коректно
працювати і завершитися. Вирішення цієї проблеми - використання вкладених try --
except та try - finally. Ось приклад p>
var p>
F: TextFile; p>
S: String; p>
... p>
begin p>
try p>
try p>
... p>
Reset (F); p>
ReadLn (F, S); p>
... p>
except p>
MessageDlg ( "Помилка роботи з файлом", mtError, [mbOk], 0); p>
end; p>
finally p>
CloseFile (F); p>
end; p>
Але
цей спосіб може не спрацювати, якщо була спроба відкриття неіснуючого
файлу (виникне іскюченіе при виконанні CloseFile (F )). p>
Спосіб
2 - Ефективний p>
Відомо,
що програма сама бере на себе обробку винятків. Але вона не завжди робить
це правильно. Тому кращим рішенням було б самому проконтролювати момент
відкриття файлу. Для цього потрібно спочатку відключити автоматичну обробку
винятків директивою (I-). А включити можна так: (I +). Потім звіритися з
значенням функції IOResult. При успішному відкритті файлу вона повертає 0. Ось
приклад: p>
(I-) p>
Reset (F); p>
(I +) p>
if IOResult0 then p>
begin p>
MessageDlg ( "Файл" + PChar (FileName) + "неіснуючої", mtError, [mbOk], 0); p>
EXIT;
//продовжувати не можна p>
end; p>
Всі
це вставте в процедуру читання файлу (у прикладі вище) замість рядка Reset (F).
Так само можна застрахуватися від збоїв вставивши цю конструкцію в процедуру
збереження файлу замість рядка Rewrite. p>
Список літератури h2>
Для
підготовки даної роботи були використані матеріали з сайту http://www.soch.imperium.by
p>