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, вызовет ошибку ввода-вывода.