Опрос размеров файлов и позиции в них




12.9.1.1. Функция FileSize(VAR f): LongInt. Эта функция возвращает реальное число записей в открытом файле f. Применительно к рис. 12.8, эта функция вернула бы значение n. Для пустого файла возвращаемое значение равно 0.

Функция FilePos(VAR f): LongInt Эта функция возвращает нашу текущую позицию в файле f. Файл должен быть открытым. Позиция в файле — это номер условной границы (см. рис. 12.8). Если файл только что открылся, то текущей позицией будет граница с номером 0. Это значит, что можно прочитать (или записать) запись с реальным номером (0+1)=1. После, например, ее прочтения позиция переместится на границу 1, и следующей можно будет прочитать запись (1+1)=2 и т.д. После прочтения последней записи в файле с реальным номером n позиция совпадает с границей с таким же номером n. Дальше записей нет. Поэтому, если FilePos {256} возвратила значение, равное FileSize, то мы находимся в конце файла за последней записью:

if FilePos(f) = FileSize(f) then { Все! Конец файла }

Все сказанное можно теперь сформулировать следующим образом:

1. В самом начале файла функция FilePos возвращает значение 0.

2. В самом конце файла функция FilePos возвращает число, равное реальному количеству записей в файле (FileSize).

3. В остальных случаях функция FilePos возвращает значение, на единицу меньшее реального номера записи, которая готова к прочтению или созданию.

Позиционирование в файлах

Операция назначения текущей позиции в файле (позиционирование) производится процедурой Seek. Процедура Seek(VAR f; N: Longint) непосредственно реализует прямой доступ в файл f. Файл должен быть открыт. Разберем механизм работы процедуры, используя рис. 12.8. В параметре N должен быть задан номер условной границы между записями. Чтобы работать с записью, имеющей реальный номер 3, мы должны задать позицию на границе перед ней, т.е. на границе с номером N=(3-1)=2. Чтобы прочитать или записать первую запись, должны задать N=0:

Seek(f, 0);

где 0 — номер границы перед первой записью. А в случае, когда необходимо, чтобы позиция имела номер последней границы (а он совпадает с числом записей на последний момент времени), следует воспользоваться вызовом:

Seek(f, FileSize(f)).

Доступ к последней записи в файле:

Seek(f, FileSize(f) - 1).

В принципе, правила назначения позиции процедурой Seek такие же, как и правила вычисления FilePos, только направлены на изменение позиции, а не на ее анализ.

На рис. 12.9 приводится пример, в котором меняются местами первый и последний компоненты. Обратите внимание на то, как после считывания последнего компонента мы вернулись на позицию назад, чтобы переписать этот же последний компонент. {257}

{ ПРИМЕР ТОГО, КАК ПОМЕНЯТЬ МЕСТАМИ ЗАПИСИ В ФАЙЛЕ } TYPE Dim = Array [1..3] of Char; { тип компонента файла } VAR f: File of Dim; { компонентный файл } ff: File; { бестиповый файл } Dfirst, Dlast: Dim; { массивы типа Dim } FS: LongInt; { длина файла f } CONST St: String[11*3]= 'AAA—BBB—CCC—DDD—EEE—FFF'; {Две процедуры для создания файла из 11 массивов типа } {Dim и его загрузки после модификации прямым доступом. } {Содержимое массивов представлено строкой длины 11*3=33 } PROCEDURE Save.St; BEGIN Assign(ff, 'DIMFILE.DAT'); Rewrite(ff, 3); BlockWrite(ff, St[1], 11); Close(ff) END; PROCEDURE Load.St; BEGIN Assign(ff, 'DIMFILE.DAT'); Reset(ff, 3); BlockRead(ff, St[1], 11); Close(ff) END; BEGIN WriteLn('Стартовое содержимое файла: ', St); Save St; Assign(f, 'DIMFILE.DAT'); { связывание f с диском } Reset(f); { открытие файла f } FS:= FileSize(f); { запоминание длины файла } if FS < 2 then begin WriteLn('Маловато записей в файле для примера!’); Halt { выход из программы } end; {if} Read(f, Dfirst); { считывается первый массив в файле } Seek(f, FS-1); { переход к последней записи } Read(f, Dlast); {считывается последний массив } Seek(f, FilePos(f)-1); { назад на одну запись } Write(f, Dfirst); { первый массив замещает последний } Seek{ f, 0); { переход в самое начало файла } Write(f, Dlast); { последний массив замещает первый } Close(f); { закрытие модифицированного файла } Load St; WriteLn { 'Итоговое содержимое файла: ', St); ReadLn { пауза до нажатия клавиши ввода } END.

Рис. 12.9 {258}

Напомним, что процедуры Write/Read и BlockWrite/BlockRead при каждом вызове перемещают границу на число прочитанных или записанных записей (компонентов или блоков).

Вызов Seek со значением N, большим чем FileSize, вызовет ошибку ввода-вывода.

Усечение файлов

Процедура Truncate(VAR f) связана с прямым доступом в файлы, но с натяжкой. Просто она увязана с процедурой позиционирования Seek.

Назначение процедуры Truncate — «отсекать хвосты» открытого файла f. Вернемся к рис. 12.8. Если текущая позиция соответствует, например, границе 2, то вызовом Truncate (f) будут удалены все идущие за ней записи с реальными номерами 3, 4,..., FileSize(f), a сама граница 2 станет концевой.

Комбинация

Seek (f, 0); { установить в начало файла }

Truncate(f); { отсечь все за границей 0 }

сделает файл f совершенно пустым. Граница 0 станет первой и последней.

После отсечения нельзя восстановить прежнюю длину (если только не создать все заново). Можно трактовать Truncate как частичное стирание (Erase). С текстовыми файлами процедура Truncate не работает.

Несколько слов о работе EOF(f) — функции анализа конца файла f. Как только текущая позиция совпадет с концевой границей (см. рис. 12.5), функция EOF (f) начинает возвращать при опросе значение True. Все остальное время она возвращает значение False.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2022-11-01 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: