Для роботи з кожним файлом описується змінна типу text:
var f:text;
Її називають файловою змінної. Якщо програма використовує кілька файлів одночасно, для кожного з них описується така змінна. Можна використовувати й одну змінну для декількох файлів, якщо вони обробляються послідовно, і кожний наступний файл відкривається після завершення роботи з попереднім. Уся робота з файлом відбувається через файлову змінну, ім'я файлу нам доведеться вказати тільки один раз наступним оператором:
assign (f,'ім'я_файлу');
де f – раніше описана файлова змінна.
Цей оператор передує відкриттю файлу й зв'язує файлову змінну з файлом на твердому або гнучкому диску. У якості імені файлу може бути зазначене фіксоване ім'я:
assign (f,'data.txt'); {буде відкриватися файл із іменем data.txt з поточної папки}
assign (f,'a:\my.dat'); {буде відкриватися файл my.dat з кореневої папки дискети}
Ім'я файлу також може бути введене користувачем із клавіатури:
Var name:string; f:text;
Begin
Writeln ('Уведіть ім'я файлу:');
Readln (name);
Assign (f,name);
. . .
або передане програмі параметром командного рядка (див. п. 5.3).
Після зв'язування слід відкрити файл. Кожний файл може бути відкритий тільки в одному із трьох режимів – для читання даних, для запису нових даних ( при цьому, якщо файл уже існував, його колишній уміст буде стертий) або для додавання даних у кінець файлу. Якщо потрібно спочатку прочитати дані з файлу, а потім переписати цей же файл, слід відкрити файл для читання, після читання закрити його й знову відкрити для запису. Відкриття файлу виконується одним із трьох операторів:
reset (f); - відкрити для читання
rewrite (f); - відкрити для запису
append (f); – відкрити для додавання
Читання або запис даних здійснюється знайомими нам операторами read,readln,writeіwriteln, але першим параметром цих операторів вказується ім'я файлової змінної:
Var a,b,c:real; f1,f2:text;
Begin
Assign (f1,'read.txt');
Assign (f2,'write.txt');
Reset (f1); {відкрили файл read.txt з поточної папки}
Rewrite (f2); { для читання, а файл write.txt для запису}
Read (f1,a,b); {Прочитали 2 числа з файлу read.txt}
C:=(a+b)/2;
Writeln (f2,c:6:2); {записали значення c і переклад рядка у файл write.txt}
. . .
Після того, як усі операції з файлом виконані, його слід закрити, особливо якщо відбувався запис або додавання даних:
close(f); {закрили файл, пов'язаний з файлової змінної f}
При роботі з файлами можуть виникнути помилки, зв'язані як з відсутністю потрібного файлу на диску, так і із проблемами читання або записи (наприклад, ми намагаємося відкрити файл для запису на захищеному від запису диску). Тому оператори відкриття файлу й читання або записи даних слід захищати директивою компілятора {$I-}. . .{$I+}, а після оператора перевіряти статус операції введення-виведення за допомогою стандартної функції Ioresult:
var f:text; name,s:string;
begin
writeln ('Уведіть ім'я файлу для відкриття:');
readln (name);
assign (f,name);
{$I-}reset(f);{$I+}
if Ioresult<>0 then begin
writeln ('Не можу відкрити файл ',name,' для читання!');
writeln ('Натисніть Enter для виходу із програми');
readln;
halt;
end;
readln(f,s);
writeln ('Перший рядок цього файлу виглядає так:');
writeln (s);
close(f);
writeln ('Натисніть Enter для виходу із програми');
readln; end.
У подальших прикладах ми для стислості не завжди будемо виконувати ці перевірки, але гарний стиль програмування припускає, що у своїх програмах Ви будете їх робити.
При читанні з файлів найчастіше обсяг, що читаються даних невідомий заздалегідь. Тому необхідна функція, що вміє визначати, чи прочитані вже всі дані:
Function Eof(Var F : Text) : Boolean; - повертає істину, якщо при читанні досягнуться кінець файлу
Function Eoln (Var F : Text) : Boolean; - повертає істину, якщо при читанні досягнуться кінець рядка
Як правило, основний цикл читання файлу із заздалегідь невідомою кількістю рядків виглядає так:
While not eof (f) do begin
{оператори для читання рядків файлу й роботи з ними}
End;
При читанні з одного файлу "змішаних" строкових і числових даних слід перевіряти, дійсно чи в потрібних рядках файлу втримуються числа. Для цього можна використовувати стандартну процедуру val. Як правило, формат файлів, що розуміються тієї або інший програмою, вибирається програмістом, і важливо передбачити реакцію програми на помилковий формат вихідних даних. Допустимо, наша програма являє собою найпростіший телефонний довідник, що включає імена абонентів і по одному телефонному номеру на кожне ім'я. Формат файлу, що зберігає дані довідника, також виберемо найпростішим:
Прізвище1
Номер1
Прізвище2
Номер2
і т.д., тобто, у рядках 1,3,5,… файлу втримуються прізвища абонентів, а в рядках 2,4,6,… їх номера телефонів. Приймемо також, що файл довідника називається phones.txt, існує й перебуває в тій же папці, звідки запускається програма.
var f:text;
name,phone,search:string;
number,strings:longint; error:integer; found:boolean;
begin
assign (f,'phones.txt');
reset(f);
writeln ('Уведіть прізвище абонента для пошуку:');
readln (search);
strings:=1; {Лічильник прочитаних рядків файлу}
found:=false; {Перемикач станів "знайдене"-"не знайдене"}
while not eof(f) do begin
readln (f,name); {Прочитали прізвище}
readln (f,phone); {Прочитали номер}
val (phone,number,error);
{Пробуємо номер-рядок перетворити в число}
if error<>0 then begin {якщо це не вдалося зробити - помилка}
Writeln ('Помилка - немає номера телефону! Номер рядка=', strings);
Writeln ('Натисніть Enter для виходу із програми');
Readln;
Halt;
end;
if name=search then begin
writeln ('Телефон знайдений:',number);
found:=true;
break;
end;
strings:=strings+1;
end;
close (f);
if found=false then writeln ('Телефон не знайдений!');
Writeln ('Натисніть Enter для виходу із програми');
Readln;
end.
Зрозуміло, цій програмі бракує як уміння редагувати, що відкривається їй довідник, так і гнучкості при пошуку – наприклад, вона розрізняє як різні символи рядкові й прописні букви в прізвищі, що вводиться.