Операция назначения текущей позиции в файле (позиционирование) производится процедурой 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, вызовет ошибку ввода-вывода.