Робота з нетипізованими файлами Free Pascal

Нетипізований або, за загальноприйнятою термінологією,двійковийфайл є довгим ланцюжком байт із вмістом будь-якої природи. Його основна відмінність від типізованих файлів полягає в тому, що одиницею обмінної інформації тут є група байтів фіксованої довжини(блок), в якій

відсутній розподіл полями заданих типів. Для обміну з двійковим файлом використовуються спеціальні процедури BlockRead та BlockWrite:

BlockRead (vf, buf, n_BLK [, N]); BlockWrite(vf, buf, n_BLK[, N]);

± buf - ім'я змінної (зазвичай масив типу byte), що грає роль буфера в оперативній пам'яті;

± n_BLK - кількість блоків, що беруть участь в обміні;

± N — ім'я змінної, до якої заноситься кількість блоків, які фактично взяли участь в обміні.

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

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

Двійкові файли поряд з послідовним обміном підтримують і прямий доступ до блоків, які подібно до записів у типізованих файлах нумеруються з 0. Для переходу до блоку із зазначеним номером використовується процедура Seek: Seek(vf, num_BLK);

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

Під час роботи з двійковим файлом за допомогою процедури Truncate (vf)

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

У лістингу 10.6 наводиться приклад копіювання файлу. Незалежно від структури даних, що зберігаються в файлі, що копіюється, він розглядається як двійковий. Насправді, спосіб організації даних у файлі та специфіка їх обробки визначаються програмістом. У разі необхідно скопіювати вміст файлу байт в байт, незалежно від цього, що у кожному байті перебуває. Насамперед, цією обставиною диктується вибір розміру блоку, що дорівнює одному байту. Крім того, така довжина блоку дозволяє не замислюватися над кількістю блоків, що зберігаються у файлі. На кожному кроці читання з вихідного файлу ми запитуємо кілька блоків і переписуємо в копію рівно стільки блоків, скільки вдалося прочитати. Рівність нуля цієї величини фіксує кінець операції копіювання.

buf: array [1..n_buf] of byte;vf_in, vf_out: файл;

num_in, num_out: integer;

assign(vf_in,'5.txt');reset(vf_in,1);assign(vf_out,'6.bin');rewrite(vf_out,1);repeat

until (num_in = 0)or(num_in <> num_out); close (vf_in);

У ранніх версіях систем Turbo Pascal, що функціонували під керуванням MS-DOS, надавалося велике значення обсягу порції даних, що брали участь в обміні. Системне обмеження зверху (32 767) дозволяло за один раз прочитати максимальну кількість поспіль секторів, що йдуть на диску — кластер. Це забезпечувало оптимальнушвидкість обміну. Зі збільшенням обсягу вінчестерів та зростанням розміру кластерів за оптимізацією обміну стежить електроніка, що керує роботою вінчестера. Тому завдання в програмі розміру порції даних, що зчитуються за один присід, особливої ​​ролі не грає.

Ще одна логічна перевірка (num_in <> num_out) в завершальному рядку циклу repeat пов'язана з можливим переповненням диска.

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

program reserve;uses SysUtils;const

buf: array [1..N] of byte; name1, name2: string;

if ParamCount=0 then begin

writeln('Must be: reserve file'); readln; exit;

end; name1:=ParamStr(1); assign(f1,name1);

reset(f1,1); if IOresult <> 0 then

writeln('File', name1, 'not found'); readln; exit;

end;name2:=ChangeFileExt(name1,'.BAK');assign(f2,name2);

until(rd=0)or(rd <> wr); close(f1);

Для запуску цієї програми в командному рядку має бути задано ім'я файлу, для якого створюється резервна копія. Ім'я файлу з резервною копією формується за допомогою системної функції ChangeFileExt. Заповнення файлу з резервною копією виконується за схемою, описаною в попередньому прикладі.

Тісний зв'язок між типизованими та нетипізованими файлами підкреслюється програмою bin_rec (листинг 10.8). Вона виконує такі самі дії, як і програма rec_file. Робота з полями запису тут моделюється за допомогою покажчиків.

Листинг 10.8. Програма bin_rec

program bin_rec; var

buf: array [1..17] of byte; f1: file;

ps: ^string; pi: ^integer; pd: ^double; j: integer;

p: = @ buf [10]; pd:=p; rewrite(f1,17); for j:=1 to 10 do

close(f1); writeln;reset(f1,17);

for j:=9 downto 0 do begin

seek(f1,j); blockread(f1,buf,1); writeln(ps^,pi^:4,pd^:10:4);

end; close(f1); readln;

Джерело: Кєтков, Ю. Л., Вільне програмне забезпечення. FREE PASCAL для студентів та школярів, Ю. Л. Кєтков, А. Ю. Кєтков. - СПб.: БХВ-Петербург, 2011. - 384 с.: Іл. + CD-ROM — (ІІІКТ)