Файли з довільною виборкою

 

Мета роботи. Вивчити методи проектування файлів з прямим доступом.

 

Основною одиницею роботи операційних систем (ОС) є файл. При роботі з файлами ОС створює і коректує спеціальні області в пам'яті, що відображають поточний стан файлу. Такі області називають дескрипторами файлів.

Дескриптор створюється при відкритті файлу та містить таку інформацію про файл як його ім'я, накопичувач, розмір запису тощо. ОС створює дескриптор у вільній області пам'яті і привласнює їй унікальний номер - хендл. Далі при роботі використовується не ім'я файлу, а номер його дескриптора. У ряді операційних систем програма користувача працює з простором на диску, який займає файл, не безпосередньо, а через системні буфери. Це зроблено з метою збільшення швидкості обміну. Обмін з диском відбувається порціями даних розміром в один сектор.

При обміні з файлом повинна бути визначена область даних у програмі, в яку або з якої прямуватимуть дані. Цей простір в пам'яті може належати Вашій програмі, а може бути також розташований в системному або створеному Вами проміжному буфері обміну. В даній роботі використовується перший підхід.

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

При послідовному доступі найбільш часто в якості логічних записів розглядаються рядки: послідовності байт завершені символами '\r'(повернення каретки) і '\n' (перевод рядка), які мають десяткові коди 13 і 10, відповідно. В логічних записах зберігаються як числа, так і символи. Останні зберігаються по одному байту на символ і кодуються згідно прийнятій системі кодування. Числа зберігаються в символьному вигляді. Так ціле число 128, що займаює в пам'яті два байти (16-е представлення 00 80), розташовується у файлі в виді послідовності з трьох символів '1','2' і '8'. Найбільш характерним представником файлів з послідовним доступом є текстові файли, що використовуються для зберігання програм, документів і даних.

Оскільки всі записи в послідовному файлі мають довільну довжину, то для знаходження потрібного запису програма повинна прочитувати файл спочатку і відлічити потрібну кількість пар символів '\r' і '\n'.

Файли прямого доступу мають логічні записи фіксованої довжини. В цьому випадку легко можна працювати з логічною записом, що має довільний номер. Для цього треба просто обчислити номер байта у файлі, відповідний початковому байту шуканого запису і встановити на нього вказівник запису/зчитування. Кожний запис може містити декілька полів, що мають фіксований розмір. Наприклад, записи файлу, що містить інформацію про пацієнтів деякої лікарні, можуть містити наступні поля: Прізвище, Зріст, Вага, Рік народження тощо. Символи в записах зберігаються по одному байту, а числа зберігаються в тому ж вигляді, як вони представляються в пам'яті.Наприклад, число 128 зберігається у вигляді послідовності двох байт '\x00' і '\x80'. Файли прямого доступу створюються наперед і спочатку містять порожні записи, які заповнюються або змінюються по мірі необхідності. В найпростішому випадку розмір файлу з часом не змінюється.

ОС забезпечує прямий доступ до кожного байту файлу, тобто логічний запис складається з одного байта. Файл зберігається як логічно безперервна послідовність байт. Місце у файлі, з якого починатиметься наступна операція введення/ввиведення, називаєтся вказівником введення/виведення, який зберігається в дескрипторі файлу. Після кожної операції обміну положення вказівника змінюється. Вказівник програмно доступний, тобто можна прочитати його вміст і записати в нього нову позицію для наступної операції обміну. Забезпечення складнішого доступу до файлу покладається на програміста. Розглянемо функції введення-виведення низького рівня.

Функції введення/виведення нижнього рівня не виконують буферизацію і форматування, як це роблять функції обміну інформації з потоками типу fscanf і fprint. Низькорівневі функції можуть розглядатися як безпосереднє звернення до можливостей операційної системи. В роботі використовуються наступні функції: close ( закрити файл ), lseek ( перепозиціювання вказівника файлу в задану позицію ), open ( відкрити файл ), read ( читати дані з файлу ), write ( записати дані у файл ). Оголошення для цих функцій розташовані в заголовному файлі io.h.

Перед виконанням операцій з файлом він повинен бути відкритий. Файл може бути відкритий для читання та/або запису в текстовому або двійковому вигляді.

Для відкриття файлу використовуємо функцію open. Ця функція повертає хендл файлу, який використовується при подальших операціях з файлом. При виклику функції open слід присвоїти значення, що повертається, цілочисельній змінній і використовувати цю змінну для звернення до відкритого файлу.

Прапори, що використовуються у функціях введення виведення низького рівня, містяться в заголовному файлі fcntl.h. В деяких випадках файли types.h і stat.h також використовуються для роботи з файлами.

Функція open має наступний формат

 

int open (char *pathname, int oflag[, int pmode]),

 

де pathname - ім'я файлу, що відкривається, оflag - режим відкриття. Аргумент oflag є цілим виразом, сформованим комбінацією однієї або більше наступних заголовних констант, визначених в fcntl.h (коли задається більш однієї заголовної константи, вони розділяються операціями АБО (|)):

O_APPEND - перерозташувати вказівник файлу на кінець файлу перед кожною операцією запису;

O_CREAT - створити і відкрити новий файл для запису, не дає результату, якщо файл вже існує;

O_EXCL - функція повертає помилковий код -1, якщо визначений в pathname файл вже існує; Застосовується тільки разом з O_CREAT;

O_RDONLY - відкрити файл тільки для читання; якщо цей прапор був заданий, ні O_RDWR, ні O_WRONLY не можуть бути задані;

O_RDWR - відкрити файл для читання і запису; якщо цей прапор був заданий, ні O_RDONLY, ні O_WRONLY не можуть бути задані;

O_TRUNС - відкрити і звузити існуючий файл до нульової довжини; файл повинен мати доступ для запису. Вміст файлу втрачається;

O_WRONLY - відкрити файл тільки для запису; якщо цей прапор був заданий, ні O_RDONLY, ні O_RDWR не можуть бути задані;

O_TEXT - відкрити файл в текстовому режимі (Комбінація символів повернення-каретки/переведення-рядка (CR/LF) перетворюється у переведення рядка (LF) при введенні; символ LF переводиться в комбінацію CR/LF при виведенні. Символ Ctrl-Z є ознакою кінця файлу.);

O_BINARY - відкрити в двійковому режимі. (Вказані вище переведення забороняються. Символ Ctrl-Z не є ознакою кінця файлу.).

Аргумент pmode потрібен тільки тоді, коли визначений режим відкриття O_CREAT. Якщо файл існує, pmode ігнорується. У іншому випадку pmode визначає спосіб доступу до файлу, що встановлюється після його першого закриття. Pmode є цілий вираз, що містить одну або обидві константи S_IWRITE і S_IREAD, визначених у файлі stat.h. Коли обидві константи задаються, вони розділяються операцією АБО(|). Рmode приймає наступні значення:

S-IWRITE - доступ для запису;

S-IREAD - доступ для читання;

S-IREAD | S-IWRITE - доступ для читання і запису.

Якщо доступ для запису не був заданий, файл відкривається тільки для читання

Функція повертає хендл відкритого файлу і -1 при помилці. При невдалому відкритті системна змінна errno встановлюється в одне з наступних значень:

EACCES - задане ім'я шляху є каталогом, або спроба відкрити для запису файл, який призначений тільки для читанн;

EEXIST - були визначені O_CREAT і O_EXCL прапори, але файл вже існує;

EMFILE - немає більше доступних файлів handle (дуже багато відкритих файлів);

ENOENT -файл або ім'я шляху не знайдено.

Приклад.

 

#include <fcntl.h>

#include <types.h>

#include <stat.h>

#include <io.h>

#include <stdlib.h>

main( )

{ int fn1, fn2;

fn1 = open("data1", O_RDONLY);

if (fn1 == -1) реrror("спроба відкрити ввідний файл невдала");

fn2 = open("data2”, O_WRONLY|O_TRUNC|O_CREAT, S_IREAD|S_IWRITE);

if (fn2 == -1) реrror("спроба відкрити вивідний файл невдала");

}

Для виведення повідомлень про помилку використовується функція реrror, яка разом з вказаним в ній текстовим рядком виводить в стандартний потік помилок stderr системне помилкове повідомлення, пов'язане із змінною errno.

Відкриті файли автоматично закриваються, при нормальному завершенні. Для примусового закриття файлів використовується функція int close(int handle), де handle - хендл файлу, що закривається.

Функція повертає 0, якщо файл успішно був закритий, і -1, якщо хендл handle є недійсним аргументом. При невдалому закритті системна змінна errno встановлюється в EBADF - недійсне значення хендла або була спроба записати у файл або пристрій, відкриті тільки для читання.

Приклад.

 

#include <io.h>

#include <fcntl.h>

main( )

{ int fh;

fh = open("data",O_RDONLY);

close(fh);}

 

Функція lseek переміщає вказівник запису/читання файлу в нове положення, з якого почнеться наступна операція. Формат функції

 

long lseek(int handle, long offset, int origin)

 

де handle - хендл файлу, а параметр origin визначає як використовується зсув offset для визначення нового положення вказівника:

SEEK_SET - від початку файлу;

SEEK_CUR - від поточної позиції вказівника файлу;

SEEK_END від кінця файлу.

Вказівник може бути переміщений за кінець файлу, проте файл змінить свої розміри тільки після операції запису даних в нову позицію.

При вдалому завершенні функція повертає зсув в байтах нової позиції покажчика від початку файлу. При помилці повертається -1L, при цьому системна змінна errno встановлюється в одне з наступних значень:

EBADF- (див. вище)

EINVAL - недійсне значення для origin, або позиція, щовизначається зсувом offset, вказує на дані, розташовані до початку файлу.

Приклад.

 

#include <io.h>

#include <fcntl.h>

#include <stdlib.h>

main( )

{ int fh; long роsition;

fh = open("data", O_RDONLY);

роsition = lseek (fh, 0L, SEEK_SET);

if (роsition == -1L) реrror("переміщення на початок невдале");

/* знайти поточну позицію */

роsition = lseek (fh, 0L, SEEK_CUR);

if (роsition == -1L) реrror ("переміщення на поточну позицію невдале");

роsition = lseek( fh, 0L,SEEK_END);

if (роsition == -1L) реrror("переміщення на кінець невдале");}

 

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

 

int write(int handle, char *buffer, unsigned count),

 

де handle - хендл файлу, куди буде записано count байтів інформації з буфера buffer.

Після операції запису вказівник збільщується на число записаних байт. Якщо файл був відкритий для додавання (APPEND), операція починається з кінця файлу.

Функція повертає число дійсно записаних байт. Значення, що повертається, може бути додатним, але менше count. Повернення числа -1 свідчить про помилку, при цьому змінна error встановлюється в одне з наступних значень:

EACCES - файл захищений від запису;

EBADF - недійсний хендл;

ENOSPC - недостатньо дискової пам'яті.

Приклад.

 

#include <io.h>

#include <stdio.h>

#include <fcntl.h>

char buffer[30000];

main()

{ int fh; unsigned nbytes = 30000;

int byteswritten;

if ((fh = open("с:/data/cont.dat",O_WRONLY)) == -1) {

реrror("невдала спроба відкрити вивідний файл");

exit(1); }

if ((byteswritten = write(fh, buffer, nbytes)) == -1){

реrror("Помилка запису");

else printf("Записано %d байтов\n", byteswritten);

}

Функція read застосовується для читання інформації з файлу і має формат:

 

int read (int handle, char * buffer, unsigned count);

 

де handle - хендл файлу, з якого ця функція намагається прочитати count байтів в буфер buffer. Операція читання починається з поточної позиції вказівника. Після читання вказівник файлу вказує на наступний непрочитаний символ.

Функція повертає число дійсно прочитаних символів, яке може бути менше ніж count, якщо у файлі залишалось недостатнє число байт. Якщо файл був відкритий в текстовому вигляді, значення, що повертається, може не відповідати числу дійсно прочитаних байтів. Це пояснюється тим, що кожна комбінація поверення-каретки/новий_рядок (LF) замінюється символом нового рядка (LF), і лише символ нового рядка зараховується в значення, що повертається.

При спробі прочитати за кінцем файлу повертається 0. При помилці повертається число -1 і системна змінна errno приймає значення: EBADF (Див. вище)

Приклад

 

#include <io.h>

#include <stdio.h>

#include <fcntl.h>

char buffer [60000];

main ( )

{int fh;

unsigned int nbytes = 60000, bytesread;

if ((fh = open ("conf.dat", O_RDONLY)) == -1) {

реrror ("спроба відкрити ввідний файл невдала");

exit (1); }

if ((bytesread = read (fh, buffer, nbytes)) == -1) реrror (" ");

else printf ("прочитано %u байтів з файла\n", bytesread);

}

При написанні системи управління прямим доступом до файлу нам знадобиться функція

 

int chsize(int handle, long size),

 

яка розширює або звужує файл, зв'язаний з хендлом handle до довжини, визначеної в size. Файл повинен бути відкритий з доступом для запису. Якщо файл розширяється, він заповнюється нульовими символами.

При успішній зміні довжини функція повертає 0, при помилці -1 і змінна errno встановлюється в одне з наступних значень:

EACCES - вказаний файл тільки для читання.;

EBADF - (див. вище).

ENOSPC - недостатньо місця на диску.

Приклад.

 

#include <io.h>

#include <fcntl.h>

#include <types.h>

#include <stat.h>

#define SIZE 32768L

main( )

{int fn, result;

fn = open("data", O_RDWR|O_CREAT, S_IREAD|S_IWRITE);

result = chsize (fn, SIZE); }

 

Швидкість роботи дискового накопичувача значно нижча швидкості роботи центрального процесора. Для збільшення еффективностиі введення-виведення широко використовується буферизація. Суть її полягає у відкладанні фізичної роботи з диском на більш пізній термін. Програма користувача веде обмін даних з буфером і лише у тому випадку, коли необхідні логічні записи, що не розташовані в буфері, відбувається фізичний обмін з диском.

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

Для визначеності припустимо, що файл містить інформацію про членів деякого колективу і кожний логічний запис має два поля: Прізвище - 14 символів і рік народження - цілий тип int -2 байта. Сумарна довжина запису rcrdsz=16 байт.

Зблокуємо записи в блоки по 512 байт. В 0-й блок входять 0-а, 1-а ... 31-а записи. В 1-й блок входять 32-а, 33-а ... 63-а записи тощо. Обмін інформацією з диском проводитимемо блоками, тобто розмір буфера рівний розміру блоку і рівний 512 байт.

Нехай Ваша програма працює з i-м записом. Він знаходиться в блоці bl=i*rcrdsz/512 (цілочисельне ділення) і починається в цьому блоці з байта n=i*rcrdsz%512. Якщо була задана адреса buf початку буфера обміну, в якому розташований bl-й блок, то k=buf+n указує на початок i-го запису файлу в буфері buf. Тут k і buf мають тип char*.

Логічний запис доцільно розглядати як структуру. В нашому випадку вона має вигляд:

struct _rec {char name[14]; /* Прізвище */

int gr;}; /* Рік народження*/

 

Структура _rec визначає вміст логічного запису з точки зору програміста. На диску вона зберігається у вигляді послідовності 16-ти, що не відрізняються між собою, байт, тобто логічний запис може бути розглянутий з цих двох точок зору. Відповідною структурою даних, що відображає цю неоднозначність, є об’єднання union. В нашому випадку можна рекомендувати наступну конструкцію:

 

union _bufrec {char bufrec[16];

struct _rec rec;} rbuf;

 

Тоді rbuf,bufres - це послідовність з 16-ти байт, яка є логічним записом rbuf.rec, що складається з двох полів rbuf.rec.name (прізвище) і rbuf.rec.gr (рік народження). Або в іншому трактуванні: вміст полів rbuf.rec.name і rbuf.rec.gr логічного запису rbuf.rec можуть бути розглянуті як послідовність з 16-ти байт rbuf.bufrec.

Всі дані, що використовуються при прямому доступі до файлу, доцільно зберігати як єдине ціле. Для цього визначимо тип даних AFILE.

 

typedef struct afile {

char *buf; /* Буфер обміну*/

int bz; /*Номер блоку, завантаженого в буфер обміну, спочатку -1*/

int w; /*Якщо в buf був виконаний запис, то w=1 інакше w=0*/

int rcrdsz; /* Довжина логічного запису*/

int numrec; /* Кількість логічних записів у файле*/

int handler; /* Хендл файлу*/}

AFILE;

 

На початку роботи з файлом прямого доступу слід його відкрити, заповнивши відповідним чином структуру, на яку вказує AFILE* ар.

При роботі з i-им логічним записом необхідно обчислити номер відповідного блоку bl=i*rcrdsz/512 (цілочисельне ділення) і визначити початок запису в цьому блоці n=i*rcrdsz%512. Потім слід перевірити чи не знаходиться логічний запис в буфері (bl==ap->bz). Якщо ні, то дивимося чи змінювався вміст буфера (ap->w==1). Якщо змінювався, тоді слід скинути буфер на диск в ap->bz-й блок, тобто записати вміст буфера ap->buf у файл починаючи з ap->bz*512-го байта. Далі (при bl!=ap->bz) слід записати в буфер ap->buf bl-й блок файлу, тобто ввести в буфер з файлу 512 байт, починаючи з 512*bl-й позиції, встановити новий номер завантаженого в буфер блоку ap->bz=bl і скинути прапорець зміни буфера ap->w=0. Після цього необхідний логічний запис буде знаходитися в буфері, починаючи з n-го байту.

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

 

Практична частина.

 

1. Вивчити теоретичну частину. Вміти відповідати на контрольні питання.

2. Для організації системи прямого доступу до файлу слід pозpобити наступні функції:

2.1. Функція створення файлу прямого доступу

 

int асreate (char* name, int rcrdsz, int numrec),

 

де name - ім'я створюваного файлу, rcrdsz - розмір логічного запису в байтах, numrec - кількість логічних записів у файлі.

Функцію слід організувати таким чином.

За допомогою функції open перевіряється існування файлу з ім'ям name. Якщо файл є на диску, функція асreate повертає -1.

Використовуючи функцію open, створюємо бінарний файл name з доступом для запису і читання.

Застосовуючи 2 рази функцію write, записуємо в перші 4 байта файлу розмір логічного запису в байтах і кількість логічних записів.

Змінимо розмір створеного файлу до величини 4+rcrdsz*numrec (функція chsize).

Закриємо файл (функція close).

2.2. Функція для відкриття створеного файлу прямого доступу

 

AFILE *aopen(char *name),

 

де name - ім'я файлу.

Алгоритм роботи, що рекомендується.

Зарезервувати пам'ять для структури AFILE

 

AFILE *ap=(AFILE*)malloc(sizeof(AFILE)).

 

Заповнити поля структури, для чого:

- виділити 512 байт для буфера обміну ap->buf=(char*)malloc(512);

- відкрити за допомогою функції open двійковий файл name з доступом для запису і читання і присвоїти отриманий хендл полю структури ap->handler;

- використовуючи двічі функцію read прочитати з файлу розмір логічного запису і кількість логічних записів у файлі, заповнивши поля ap->rcrdsz і ap->numrec;

- встановити ознаку зміни буфера обміну ap->w в 0;

- присвоїти полю ap->bz -1.

Повернути в програму вказівник ар на структуру AFILE.

2.3. Функція для обміну інформацією між програмою користувача і файлом прямого доступу

 

int areadwrite(AFILE *ap,int nr, char* rec, int mode ),

 

де ар- вказівник на структуру, що описує файл прямого доступу, з яким ведеться робота, nr- номер логічного запису у файлі, з яким проводиться обмін інформацією, rec – буфер користувача, рівний за розміром довжині логічного запису і що використовується для введення-виведення записів, mode - режим обміну (0 - читання, 1 - запис ).

Функція повинна виконувати наступні дії.

Обчислити номер блоку bl=nr*rcrdsz/512, в якому розташований логічний запис з номером nr і початок запису в цьому блоці n= nr *rcrdsz%512.

Перевірити чи не знаходиться логічний запис nr в буфері (bl==ap->bz). Якщо ні, то дивимося чи змінювався вміст буфера (ap->w==1). Якщо змінювалося, то слід скинути буфер на диск в ap->bz-й блок, тобто, використовуючи функції lseek і write, записати вміст буфера ap->buf у файл починаючи з 4+ap->bz* 512-го байта. Далі (при bl!=ap->bz) слід:

- записати в буфер ар ->buf bl-й блок файлу, тобто застосовуючи функції lseek і read, ввести в буфер з файлу 512 байт, починаючи з 4+512*bl -ї позиції;

- встановити новий номер ap->bz=bl завантаженого в буфер блоку;

- скинути прапорець зміни буфера ap->w =0. Логічний запис nr знаходиться в буфері ap->buf, починаючи з n-го байта і з ним можна вести обмін інформацією залежно від значення змінної mode;

- при читанні (mode=0), дані переписуються з буфера обміну в призначений для користувача буфер:

 

for(i=0;i<rcrdsz;i++)rec[i]=(ap->buf+n)[i].

 

- при запису (mode=1) проводиться обмін інформацією в зворотньому напрямі:

for(i=0;i<rcrdsz;i++)(ap->buf+n)[i]=rec[i]

 

і встановлюється ознака зміни вмісту буфера обміну ap->w=1.

 

2.4. Функція закриття файлу прямого доступу

 

int асlose(AFILE *ap),

 

де ар - вказівник на структуру AFILE, яка описує файл прямого доступу, що закривається.

Функція працює таким чином.

Якщо вміст буфера ap->buf змінювався (ap->w==1), то слід встановити вказівник запису-читання на початок завантаженого блоку (4+ap->bz*512) і записати буфер на диск. Хендл файлу знаходиться в ap->handler.

За допомогою функції free слід послідовно звільнити пам'ять, що зайнята буфером ap->buf, закрити файл з хендлом ap->handler і звільнити пам'ять від структури AFILE, на яку вказує змінна ар.

3. Для перевірки правильності роботи системи прямого доступу до файлу слід використовувати наступну функцію main

 

typedef struct afile {

char *buf;

int bz;

int w;

int rcrdsz;

int numrec;

int handler;} AFILE;

#include <stdio.h>

#include <io.h>

#include <fcntl.h>

#include <stat.h>

#define R 0

#define W 1

struct _rec {char name[14]; int gr;};

int асreate (char*, int, int ); /*Прототипи */

AFILE *aopen(char *) *ap;

int areadwrite(AFILE*, int, char*, int );

int асlose(AFILE *ap); /* функцій */

main()

{ int i, nr;

char s[13],c,c1;

union _bufrec {char bufrec[16]; /*Буфер*/

struct _rec rec;} rbuf; /* rористувача */

printf("\nВведіть ім'я нового файлу прямого доступа\

(100 записів по 16 байт): ");

gets(s);

if(-1==acreate(s,16,100))

printf("\nЧи будете працювати з існуючим файлом %s!",s);

ap=aopen(s); /* Відкриття файлу прямого доступа*/

do { /* Основний цикл*/

for(i=0;i<16;i++)rbuf.bufrec[i]='\0'; /* Обнулення логічного запису*/

puts("\nHомеp запису ?");

scanf("%d",&nr);

areadwrite(ар, nr, rbuf.bufrec, R); /* Читання логічного запису */

/* Виведення запису на экран*/

printf("\nЗапис #%d. Вміст полів:\n Ім’я=\" %s\". \

Рік народження = %d",nr,rbuf.rec.name,rbuf.rec.gr);

puts(" \nЧи будете змінювати/формувати запис (у/n)?");

c=getche();

if(c=='y')

{puts("\nПрізвище?"); /*Введення полів логічного запису з клавіатури*/

scanf("%s",rbuf.rec.name);

puts("\nРік народження ?");

scanf("%d",&rbuf.rec.gr);

areadwrite(ар, nr, rbuf.bufrec, W); /* Запис логичного запису на диск */

}

puts("\nЧи будете працювати з файлом ще (у/n)?");

c1=getche();

}

while(c1=='y');

асlose(ар); /* Закриття файла*/

}

Зверніть увагу на використовування змінної типу об’єднання rbuf.

 

Контрольні питання.

 

1. Що таке дескриптор файлу і його хендл?

2. В чому полягає процес відкриття файлу?

3. Що таке логічний запис?

4. Охарактеризуйте послідовний доступ до файлу.

5. В чому суть довільного доступу до файлу?

6. Який режим доступу до файлів забезпечують системи UNIX і MS DOS?

7. Яку роль в організації файлових систем відіграє вказівник запису/читання?

8. Які функції дозволяють відкривати і закривати файли?

9. Яка функція і як забезпечує установку позиції запису/читання у файлі?

10. Як прочитати (записати) інформацію в (з) файл(а)?

11. Чи можна змінювати розмір існуючого файлу?

12. Навіщо застосовують буферизацію при роботі з файлами?

13. Висловити алгоритм буферизації.

14. Привести алгоритм організації прямого доступу до файлу.

15. Навести приклади форматів логічних записів.

16. Які типи даних рекомендується застосовувати при роботі з логічними записами?

17. Який виграш дає робота вживання структури AFILE з файлами прямого доступу?

18. Яку інформацію і навіщо рекомендується додавати в початок файлу прямого доступу?

Лабораторна робота №6.