Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции_Паскал.doc
Скачиваний:
2
Добавлен:
21.09.2019
Размер:
1.21 Mб
Скачать

3. Запис даних у файл

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

rewrite(TxtFile: text);

До її виклику файлова змінна повинна бути прив'язана до імені файлу на диску за допомогою assign. Якщо файл не існував, то rewrite створить його, якщо існував, той уміст буде стерто. У будь-якому випадку файл буде порожнім, а покажчик запису розташується на початку файлу.

Для запису використовуються процедури

write(TxtFile: text, p1: type1, p2: type2, ... pN: typeN);

writeln(TxtFile: text, p1: type1, p2: type2, ... p: type);

Тут як параметри p1, p2, ... p можна використовувати не тільки змінні, але і вирази: числових типів, рядкові, символьні і логічні (boolean). На відміну від write, writeln після запису у файл значень p1, p2, ... p переводить покажчик запису на початок нового рядка; writeln з одним параметром (текстовий файл) лише переводить покажчик на новий рядок.

Так само як і у випадку з читанням з файлу, після того як усі дані записані файл потрібно закрити за допомогою close.

Приклад 2 (запис у файл). Нехай даний довільний текстовий файл, потрібно одержати інший файл, у кожнім рядку якого записана довжина відповідної рядка вихідного файлу:

program WriteLength;

var f1,f2: text;

s: string;

begin

assign(f1,'writelen.pas'); reset(f1);

assign(f2,'result.txt'); rewrite(f2);

while not eof(f1) do begin

readln(f1,s);

writeln(f2,length(s));

end;

close(f1); close(f2);

end.

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

append(TxtFile: text);

Якщо файл відкритий за допомогою append, то весь його вміст зберігається. При завершенні дописування в кінець файлу його також варто закрити за допомогою close.

Двійкові файли

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

Для всіх обговорюваних нижче файлів можна виконувати ті ж процедури відкриття, закриття і прив'язки, що і для текстових: Append, Assign, Close, Reset, Rewrite. Крім того, з'являється процедура Truncate(var f: file), що знищує весь уміст файлу, що знаходиться після поточного покажчика читання.

Двійкові файли будемо поділяти на типізовані і нетипізовані.

1. Типізовані файли

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

Оголошують типізовані файли так:

var f: file of тип_елемента;

Як тип елемента можна використовувати як прості типи, так і структуровані (масиви, записи і т.п.).

2. Нетипізовані файли

Крім визначених в авторській версії мови типізованих файлів і текстових файлів, Turbo Pascal містить поняття нетипізованих файлів чи файлів без типу. Відповідні змінні описуються за допомогою службового слова file (без of), наприклад:

var

Data:file;

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

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

Assign(Data, 'MYDATA.DTA') ; Reset(Data,200) ;

Розмір запису задається в байтах; якщо другий параметр опущений, то передбачається розмір у 128 байтів. При цьому варто враховувати дві обставини. По-перше, для забезпечення максимальної швидкості обміну довжина запису повинна бути кратною розміру фізичного сектора диска - 512 байтів. З іншого боку, потрібно пам'ятати, що загальний розмір файлу може не бути кратний обраному розміру запису (останній запис може бути неповним). Для того, щоб гарантовано забезпечити повне читання усього файлу, потрібно установити розмір запису рівним 1.

Для організації обмінів з нетипізованими файлами в мові Turbo Pascal призначені дві стандартні процедури:

BlockRead

BlockWrite

Як робочий буфер для обмінів використовується змінна, котру необхідно описати в програмі і розмір якої не повинний бути менше розміру запису, встановленого в параметрах Reset чи Rewrite. Ім'я цієї змінної вказується у виклику процедури BlockRead (BlockWrite). Заголовок першої процедури описується так:

BlockRead ( var F:file,- var Buf; Count:word )

BlockRead ( var F:file; var Buf; Count:word; var Result:word)

Тут F - ім'я нетипізованого файлу, з якого відбувається читання; Buf - змінна-буфер (цей параметр передається як нетипізований); Count - число записів, що читаються за один виклик. Крім цього, BlockRead може містити ще один параметр - Result, у який розташовуєтьс число фактично прочитаних записів. Змінна F повинна бути описана як нетипізований файл, зв'язана з конкретним фізичним диском процедурою Assign; файл повинний бути відкритий процедурою Reset.

При виконанні цієї процедури записи, що читаються з F розташовуються в опертивній пам’яті, починаючи з першого байта області, яку займає змінна Buf.

Аналогічно описується стандартна процедура BlockWrite:

BlockWrite ( var F:file,- var Buf; Count:word )

BlockWrite ( var F:file,- var Buf; Count:word; var Result:word )

Зміст параметрів той же, що й у параметрів попередньої процедури, з тією лише різницею, що файл F повинний бути підготовлений для запису процедурою Rewrite. Уміст перемінної Buf цілком розміщується у файл F, починаючи з поточного запису.

В обох процедурах потрібно стежити за тим, щоб розмір змінної-буфера Buf був рівним RecSize*Count, де RecSize -розмір запису, зазначеної в процедурах Reset чи Rewrite, Count - число записів,що читаються (записуються) , тобто значення параметра.

Якщо при записі у файл процедурою BlockWrite на диску не виявиться вільного простору чи при читанні з файлу процедурою BlockRead розмір буфера виявиться менше зазначеного вище добутку, то відбудеться наступне: якщо останній параметр Result у цих викликах не заданий, то виникне помилка введення-виведення; якщо параметр Result заданий, то помилка не буде зафіксована, а після виконання процедури його значення не буде збігатися зі значенням параметра Count. Останню обставину можна перевірити, порівнявши два зазначених значення.

Приведемо простий приклад використання нетипізованих файлів для копіювання інформації, узятий з підсистеми оперативної допомоги Turbo Pascal. У наступній програмі використовуються стандартні функції ParamCount і ParamStr, що обробляють строкові параметри, передані програмі при її запуску з командного рядка чи через альтернативу Run/Parameters . .. інтегрованого середовища. Функція ParamCount повертає загальне число переданих параметрів, а функція ParamStr - рядок, що містить параметр із зазначеним порядковим номером.

program FileCopy;

{Копіювання файлу; файл-джерело і файл-приймач}

{задаються у виді строкових параметрів програми. }

{Спрощений варіант (без контролю помилок) }

const RecSize = 512; {розмір буфера обміну)

var

FileIn,

FileOut : file; { копіюємо FileIn -> FileOut }

NumRead, { число фактично лічених } NumWritten: Word; { і фактично записаних записів }

Buf: array[l..RecSize] of char; {буфер обміну }

begin

if ParamCount<2 then Halt;{ перевірка числа параметрів }

{ Відкриваємо файл-джерело )

Assign(FileIn,ParamStr(l));

{$I-}

Reset(FileIn,l);

{$I+}

if IOResult <> 0 then begin

Writeln('Файл-джерело не знайдене'); Halt end;

{ Відкриваємо файл-приймач )

Assign(FileOut,ParamStr(2));

Rewrite(FileOut,1);

WriteLn('KonnpyeM ',ParamStr(l),' -> ,ParamStr(2));

{ Цикл копіювання }

repeat

BlockRead(FileIn,Buf,RecSize,NumRead);

BlockWrite(FileOut,Buf,NumRead,NumWritten);

until(NumRead = 0) or (NumWritten <> NumRead);

WriteLn('Копіювання закінчене');

{ Закриваємо файли }

Close(FileIn);

Close(FileOut)

end.

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