12.9.2. Позиционирование в файлах
Операция назначения текущей позиции в файле (позиционирование) производится процедурой 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 приводится пример, в котором меняются местами первый и последний компоненты. Обратите внимание на то, как после считывания последнего компонента мы вернулись на позицию назад, чтобы переписать этот же последний компонент.
- 258 -
| { ПРИМЕР ТОГО, КАК ПОМЕНЯТЬ МЕСТАМИ ЗАПИСИ В ФАЙЛЕ }
| 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
- 259 -
Напомним, что процедуры Write/Read и BlockWrite/BlockRead при каждом вызове перемещают границу на число прочитанных или записанных записей (компонентов или блоков).
Вызов Seek со значением N, большим чем FileSize, вызовет ошибку ввода-вывода.