Робота з нетипізованими файлами 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 — (ІІІКТ)