Главная страница

 

ДОМ
ИНФОРМАЦИОННЫХ ТЕХНОЛОГИЙ

Информатика и программирование
Информационные технологии
Компьютерные сети
Информационная безопасность
Как заработать в сети Интернет
Информатика и программирование
Операційна система Windows
Текстовий редактор Word
Редактор електронних таблиць Excel
Мова програмування Pascal
Язык программирования Pascal

Теоретичний матеріал за темами:

1.              Загальні вказівки

2.              Програмування лінійних структур, обчислення арифметичних виразів

3.              Програмування розгалужених обчислюваньних процесів

4.              Програмування циклічних обчислювальних процесів

5.              Обробка текстових даних

6.              Використання типу Record

7. Використання підпрограм

8. Організація модулів

9. Робота з файлами

10. Використання динамічних змінних

  return_links(); ?>

Copyright © Евгений Литвиненко, 2007
Использование без разрешения автора запрещено

Робота з файловими змінними

 

Дотепер дані вводилися в програму через клавіатуру, тобто з неодмінною участю людини. Такий спосіб введення інформації називається інтерактивним режимом уведення. Можливий і інший підхід, що ґрунтується на використанні набору даних, підготовлених заздалегідь і, що зберігається у виді файлу на магнітному носії. Інакше кажучи, альтернативою інтерактивному режиму є такий спосіб уведення, при якому інформація надходить із джерела, що фізично існує поза програмою. Цей процес звичайно називають зчитуванням даних із зовнішнього файлу (чи просто з файлу). Зазначений спосіб знаходить широке застосування у процесі обробки інформаційних масивів дуже значного обсягу, коли інтерактивний режим стає занадто обтяжним і малоефективної.
Другим мотивом використання файлів є те, що він може бути створений якоюсь іншою програмою. Таким чином, файл стає сполучною ланкою між різними задачами. Нарешті, останнє немаловажливе розуміння: якщо вхідні дані надходять у програму із зовнішнього файлу, то присутність користувача в момент фактичного виконання програми стає необов'язковою.
Файл - це іменована область зовнішньої пам'яті комп'ютера (твердого диска, гнучкої дискети,...), що містить логічно зв'язану сукупність даних.
Мовою Паскаль можна створювати три типи файлів: текстовий, типізований, нетипизований, котрі в програмі (у розділі VAR) визначаються наступним образом:

<файлова змінна> : text;
< файлова змінна> : file of < тип компоненти >;
< файлова змінна > : file.

<файлова змінна> - це логічне ім'я файлу, що використовується в програмі; < тип компоненти > - компонентом файлу може бути як перемінна як базового типу, так і структурного. Структурний тип визначає дані типу "запис" (record).
"Запис" - це логічно зв'язана сукупність декількох даних. До даних типу RECORD можна звертатися як до всієї сукупності даних, так і до її окремих даних (елементів). Для звертання до окремих елементів "запису" використовується уточнене ім'я.
Уточнене ім'я складається з ідентифікатора "запису", десяткової крапки й ідентифікатора елемента запису. У свою чергу кожен елемент "запису" може бути "записом". Тоді, для звертання до внутрішнього елемента необхідно послідовно перелічити через десяткову крапку всі ідентифікатори ієрархічно вкладених "записів", починаючи від зовнішнього імені до внутрішнього, останнім у цій послідовності є ідентифікатор самого елементу.
Під час використання структурного типу компоненти "запис" необхідно повідомляти його в програмі в розділі TYPE.
Приклад:

ТУРЕ { запис даних про студента }
   RecFile = RECORD { ознака початку запису }
                        Fam, Name, Otch : string[15];
                        GodR : word;
                        Ngrup : string[10];
                  END; { кінець запису }
VAR
   F1 : Text;
   F2 : File of byte;
   F3 : File of RecFile;
   F4 : File;
   Buf : RecFile; {_2буфер уведення-висновку_0, у який зчитуються дані компоненти файлу}

У цьому фрагменті програми F1- файлова змінна текстового типу, F2 і F3 – файлові змінні типізованого типу, причому F2 може містити тільки байтові компоненти, а у файлі F3 кожен компонент представляє із себе "запис" із трьох елементів, F4- файлова змінна нетипизованого типу. Уточнені імена елементів запису Buf: Buf.Fam, Buf.Name, Buf.Otch, Buf.God, Buf.NGrup.
У першу чергу під час роботи з файлами необхідно привести у відповідність файлову змінну й ім'я файлу, з яким він зберігається на зовнішньому носії. З цим ім'ям працює операційна система (ОС) DOS. Відповідність установлюється за допомогою процедури:

ASSIGN (< ф.з.>, < ім'я файлу>);

Тут < ф.з.> - файлова змінна; < ім'я файлу > - це повне ім'я файлу, яке містить у собі шлях доступу, безпосереднє ім'я файлу і розширення.
Наприклад:

ASSIGN (F1, 'a:\Tp5\DAT\St629.DAT');
ASSIGN (F2, 'Dannye.DAT').

Якщо не зазначений шлях до файлу, то чи запис зчитування здійснюється в поточний директорій.
Як ім'я файлу в процедурі ASSIGN можна вказувати логічний пристрій з наступного списку: CON, PRN, AUX.
CON - це ім'я консолі. На персональному комп'ютері (ПК) під консоллю розуміється сукупність двох пристроїв: клавіатури і дисплея. Клавіатура використовується для введення інформації, а дисплей для виводу.
PRN - це стандартне ім'я принтера. В ОС PRN стандартно призначається LPT1. У модулі Printer Паскаля оголошена файлова перемінна Lst. Тому для відображення даних на принтер досить підключити модуль Printer до програми, а в процедурах Write і Writeln першим аргументом записати ім'я файлової перемінної Lst:
Приклад висновку інформації без використання модуля Printer:

VAR F : File;
BEGIN
   Assign(F, PRN);
   ReWrite(F);
   Writeln(F, 'Приклад використання Л.У. - PRN');
   Close(F);
END.

AUX - це ім'я комунікаційного порту. Звичайно їх буває два в ПК: СОМ1 і СОМ2. Стандартно AUX призначається СОМ1. Цей порт звичайно використовується для підключення нестандартних пристроїв. Наприклад, "миші", графобудівника і т.ін.
Перш ніж почати обробку файлу необхідно виконати деякі операції по роботі з пристроєм, на якому зберігається або буде зберігатися файл. Так, наприклад, під час створення файлу необхідно: виділити область пам'яті на зовнішньому пристрої, у яку будуть записуватися дані файлу; запам'ятати ім'я файлу й адресу цієї області.
Якщо має бути робота з файлом, що вже існує на зовнішньому носії, то необхідні наступні дії: по зазначеному імені файлу знайти адреси цього файлу;
установити голівку пристрою на початок файлу.
Ця сукупність операцій називається ініціацією файлу чи "відкриттям" файлу. Ініціюється файл за допомогою процедур Reset і ReWrite. За допомогою процедури Reset ініціюється, тобто відкривається раніше створений файл. За допомогою процедури ReWrite ініціюється файл для запису, тобто файл, що створюється.
Синтаксис:

Reset(< ф.з.> [,< розмір запису в байтах >]);
ReWrite(< ф.з.> [,< розмір запису в байтах >]);

Другий аргумент вказується тільки для нетипизованих файлів. Текстові файли можна ініціювати також і процедурою Append:

Append(< ф.з.>);

У цьому випадку раніше створений файл відкривається для додавання даних у кінець файлу.
Завершивши роботу з файлом, необхідно його закрити. При закритті файлу ОС підраховує розмір файлу в байтах і запам'ятовує його. Крім того, запам'ятовується також інформація про дату і час створення файлу чи його останньої модифікації (коректування). Закриття файлу даних здійснюється процедурою Close:

Close(< ф.з.>);

При зчитуванні даних з раніше створеного файлу кінець файлу можна визначити з допомогою функції EOF:
EOF(< ф.з.>);

Ця функція має значення TRUE у процесі зчитування маркера кінця файлу. У противному випадку вона буде мати значення FALSE. Дана функція звичайно використовується для організації циклу читання всіх компонентів файлу, наприклад:

while not EOF(F1) do begin
...
< зчитування й обробка компонент файлу >
...
end;

Безпосереднє введення інформації здійснюється процедурами READ і READLN, а вивід (запис) інформації - WRITE і WRITELN. Особливістю їхнього застосування до файлу є обов'язковість вказівки файлової змінної як першого параметра у списку елементів:

Read(< файлова змінна >, < список введення >);
ReadLn(< файлова змінна >, < список введення >);
Write(< файлова змінна >, < список виводу >);
WriteLn(< файлова змінна >,< список виводу >).

Текстовий файл - це сукупність рядків змінної довжини. Змінна довжина рядків визначає наявність маркерів, що відзначають кінець рядка. Як маркери використовуються два керуючі символу "Перехід рядка" і "Повернення каретки", їх десяткові коди: #10, #13. Назви керуючих символів "Перехід рядка"(LF – Line Feed) і "Повернення каретки"(CR - Carriage Return) узяті за аналогією роботи з пишучою машинкою.
Кінець рядка можна визначити за допомогою функції EOLn:

EOLn(< ф.з.>);

Для запису даних у файл використовуються процедури WRITE і WRITELN:

Write(< ф.з.>, < список виводу >);
Writeln(< ф.з.>, < список виводу >).

За процедурою WRITE значення даних зі списку запишуться у файл підряд без усяких роздільників. Тому програміст, використовуючи процедуру WRITE, повинний подбати про роздільники між даними, якщо вони потрібні. За процедурою WRITELN у файлі після кожного виведеного значення будуть записані ознаки кінця рядка.
Для читання даних з файлу використовуються процедури READ і READLN:

Read(< ф.з.>, < список вводу >);
Readln(< ф.з.>, < список вводу >);

За процедурою READ з файлу вибирається стільки символів, скільки зазначено в описі поточної змінної, що належить списку вводу. Обрана послідовність символів привласнюється поточній змінній. Ця сукупність операцій повторюється для всіх елементів списку вводу. За процедурою READLN з файлу послідовно зчитуються рядки і привласнюються змінним. Якщо обраний рядок має більшу кількість символів, ніж зазначено в описі поточної змінної, то вона обрізається до зазначеної довжини, при цьому частина інформації губиться. Тому необхідно стежити за відповідністю довжин змінних, що записуються у файл і що зчитуються з файлу.
Приклад:

Var Fio, Otch : string[15];
       Name : string[10];
       i : integer;
      F : text;
Begin
   Assign(F, 'St629.DAT'ReWrite(F); { відкриття файлу для запису }
    for і:=1 to 5 do { обмежимося введенням п'яти студентів }
     begin
       Write('Прізвище: ');
       Readln(Fam);
       Write('Ім'я: ');
       Readln(Name);
       Write('По батькові: ');
       ReadLn(Otch);
      Write(F, Fam, Name, Otch);
  end;
  close(F);
  WriteLn(' Прізвище Ім'я По батькові');
  Reset(F); { відкриття існуючого файлу }
   for i:=1 to 5 do
    begin
     Read(F, Fam, Name, Otch);
     Write(Fam:16, Name:11, Otch:15);
   end;
  close(F);
End.

Компоненти типізованого файлу можуть бути наступних типів:

  1. базового: byte, word, longint, integer, real, запис, char, string;
  2. структурного;
  3. регулярного.

При цьому усі компоненти файлу мають той самий тип. Це означає, що довжина компоненти фіксована. Описується такий файл у програмі в такий спосіб :

Var
F1 : File of byte;
F2 : File of string[80];
F3 : File of real;
. . .
F : File of RecFile;

Тут F1, F2, F3, F - це файлові змінні, котрі вказують на файли, компоненти яких відповідно є типу byte, string, real і record.
Читання компонентів файлу виконується процедурою:

Read(< ф.з.>, < список вводу >);

Запис компонентів у файл виконується за допомогою процедури:

Write(< ф.з.>, < список виводу >);

Приклад:

Var
    X, Y : array[1..100] of integer; { масиви координат }
    F : file of real;
    i : byte;
Begin
   . . .
   < оператори по введенню 100 значень координат X, Y >
   . . .
   Assign(F, 'Coor.dat'); { файл буде створюватися в поточному каталозі }
   ReWrite(F); { відкриття файлу для запису }
   For і:= 1 to 100 do
   Write(F, X[і], Y[і]); { запис координат у файл }
   Close(F);
End.

У наведеному фрагменті програми координати записані послідовними парами X, Y. При такій організації файлу відбувається часте звертання до зовнішнього носія, це призводить до уповільнення роботи програми, що особливо помітно у процесі роботи з великими обсягами даних. Тому рекомендуються дані записувати у файл і зчитувати з файлу великими блоками, приблизно кратним 512 байтам. Відповідно до цього модифікуємо програму в такий спосіб:

Type
    Coord = array[1..100] of integer; { масиви координат }
     . . .
Var X, Y : Coord; { масиви координат }
       F : file of Coord; { файл регулярного типу }
       i : byte;
Begin
   . . .
  < оператори по введенню 100 значень координат X, Y >
   . . .
   Assign(F, 'Coor.dat'); { файл буде створюватися в поточному каталозі }
   ReWrite(F); { відкриття файлу для запису }
   Write(F, X); { запис масиву координат Х в файл }
   Write(F, Y); { запис масиву координат Y у файл }
   Close(F);
End.

Тепер у файлі спочатку записані 100 координат Х, а потім 100 координат Y. Дані файлу ми записали двома великими блоками по 600 байтів кожний. Зчитування координат з файлу виконується аналогічно, у програмі потрібно замість процедури REWRITE використовувати процедуру RESET, а замість пропозиції WRITE використовувати пропозицію READ.
Добре структуровані дані, наприклад, дані про який-небудь об'єкт, зручно
описувати типом "запис". У цьому випадку компонента файлу буде структурного типу.
Приклад:

Type RecFile = record { запис даних по студенту }
Fam, Name, Otch : string[15];
GodR : word;
NGrup : string[10];
      end;
Var i : integer;
       Buf : RecFile;
       FilStud : file of RecFile;
Begin
   Assign(FilStud, 'Stud.dat');
   ReWrite(FilStud);
    WriteLn('Уведіть дані по студентах:');
    For і:= 1 to 10 do { обмежимося 10 записами }
      begin
                   Write('Прізвище : ');
Readln(Buf.Fam);
Write('Ім'я : ');
Readln(Buf.Name);
Write('По батькові : ');
Resdln(Buf.Otch);
Write('Рік народження : ');
Readln(Buf.God);
Write('N групи : ');
Readln(Buf.NGrup);
{ запис даних у файл }
Write(FilStud, Buf); { Buf - звертання до всього запису }
      end;
   Close(FilStud);
End.

Читання компонентів типізованого файлу можна здійснювати як послідовним, так і прямим методом доступу. Послідовний доступ - це є доступ до компонента файлу тільки після перебору всіх попередніх. Прямий доступ - це є доступ відразу до зазначеного компонента.
Тому що типізовані файли мають компоненти фіксованої довжини, існує можливість організувати прямий доступ. Для організації прямого доступу до компонент файлу існують стандартні процедури Seek, FilePos, FileSize :

Seek(< файлова змінна >,< номер компоненти >);
FilePos(< файлова змінна >);
FileSize(< файлова змінна >).

Процедура Seek здійснює прямий доступ до будь-якого компонента файлу. Тут < номер компоненти > - позиція покажчика компонент файлу. Вона може приймати наступні значення:
+1 - установити покажчик на наступну компонент;
-1 - установити покажчик на попередню компонент;
і - установити покажчик на i-ту компоненту.
Процедура FilePos визначає номер поточної позиції у файлі, а точніше номер поточної компоненти.
Процедура FileSize визначає розмір зазначеного файлу - кількість компонент. Нумерація компонентів починається з нуля.
Приклад:

Type RecFile = record { запис даних по студенту }
Fam, Name, Otch : string[15];
GodR : word;
NGrup : string[10];
     end;
Var i : integer;
      Buf : RecFile;
      FilStud : file of RecFile;
Begin
   Assign(FilStud, 'Stud.dat');
   Reset(FilStud);
   i:= FileSize;
   WriteLn('У файлі ', і, ' компонент');
    Seek(FilStud, і-1);
    Read(FilStud, Buf);
    Buf.God:= '1973';
    Seek(FilStud, -1);
    Write(FilStud, Buf);
    Close(FilStud);
End.

Відкриваючи типізований файл процедурою RESET, можна цей файл не тільки читати, але і записувати в нього нову інформацію. При цьому файл повинний уже існувати на диску.
Нетипізовані файли можуть містити у своєму складі будь-які типи компонент. При цьому правильність запису і зчитування цих компонентів цілком покладається на програміста. Довжина компонентів може бути різною. Для відкриття нетипізованих  файлів використовуються процедури Reset, ReWrite:

Reset(< файлова змінна >, < max розмір буфера >);
ReWrite(< файлова змінна >, < max розмір буфера >).

Тому що за одне звертання до нетипізованого файлу можна зчитувати не одну компоненту, а менше, і тому що довжини компонентів можуть бути різні, то в процедурах Reset і ReWrite указується максимальний розмір буфера вводу-виводу в байтах.
Читання компонентів з файлу і запис їх у файл виконується процедурами BlockRead і BlockWrite:

BlockRead(< файлова змінна >, < буфер >,<  компонент, що зчитуються за один раз >, [,< декілька компонентів >]);
BlockWrite(< файлова змінна >,< буфер >,< компонент, що записується>, [,<  компоненти, що записуються >]).

Четвертий параметр необов'язковий. Він формується системою і використовується для перевірки правильності завершення операцій читання або запису.
Нетипізовані файли рекомендується використовувати для організації ефективної роботи з файлами, тому що вони дозволяють працювати, по-перше, з компонентами різної довжини, і, по-друге, зі змінним числом компонент, що обробляються.

Copyright © Eugene, 2007
e-mail: webmaster@ITDom.info
Rambler's Top100 Рейтинг@Mail.ru