При прямом доступе сначала вычисляется значение указателя, определяющего номер записи (номер компонента), после чего можно обеспечить прямой доступ к нужной записи, используя процедуру позиционирования
SEEK ( имя_файла_в_прог, физ _номер_записи );
Далее может следовать:
v либо чтение указанной записи из файла,
v либо занесение подготовленной записи в файл на указанное место вместо прежней записи (примерно так может быть выполнена корректировка или замена указанной записи в файле).
Для обеспечения прямого доступа необходимо следующее:
v файл должен быть типизированным (фиксированная, постоянная длина записи);
v данные (записи файла) располагаются в областях на диске, имеющих последовательные номера (нумерация областей, начиная с нуля, осуществляется автоматически);
v обратить внимание: первая логическая запись будет размещена в физической области с нулевым номером, вторая логическая – в первой физической и т.д. В Seek (…) указывается физический номер записи
v размещение записей желательно без пропусков.
|
|
v использование процедур, обеспечивающих
· контроль положения указателя чтения FilePos (…);
· позиционирование указателя чтения в файле Seek (…);
v желательно (настоятельно рекомендуется) наличие в записи признака, преобразующегося в физический номер записи, так называемого ключа записи. Простейший метод преобразования значения ключа в номер записи:
Номер_зап = Ключ_тек – Ключ_мин
Возможны и более сложные алгоритмы преобразования значения признака из записи в физический номер записи в файле, но, так или иначе, необходимо наличие связи между ключом записи и её номером.
v записи в файле должны быть рассортированы по ключевому признаку в порядке возрастания, если ключевой признак преобразуется в физический номер записи.
Не исключается вариант, когда значения ключевого признака записи образуют не строго последовательный ряд значений, а ряд с пропусками, пустотами. Чем больше таких пустот, тем более неэффективной будет работа с таким файлом. Наличие таких пустот приведёт к следующим недостаткам:
o потери в используемой памяти («пустые» записи внутри файла);
o необходимо выполнить предварительное резервирование места для записей – что-то вроде разметки файлового пространства, то есть занесение в файл только пустых записей;
o заполнение файла реальными записями в файл прямым доступом в соответствии со значениями их ключей;
o контроль записей при чтении из файла, чтобы не работать с пустыми записями.
Пример.
В следующей программе, используя прямой доступ к записям файла, созданного в предыдущей программе, требуется подсчитать общую сумму зарплаты тех рабочих, чьи табельные номера вводятся с клавиатуры. Предполагается, что при создании файла были использованы табельные номера в интервале 101-999 и запись с номером 101 занимает первое место в файле, за ней следует запись с табельным номером 102 и т.д. Таким образом, табельный номер и есть ключ записи, который будет преобразован в физический номер записи
|
|
program file_2;
Type
tz=record
fio:string[20];
tn:integer;
Zp:real
end;
Var
zap:tz;
fout:file of tz;
tn1,tn2,n:integer;
s:real;
filename:string;
ans: string;
Begin
writeln('введите имя файла ');
readln(filename);
assign (fout, filename);
reset(fout);
s:=0;
Repeat
readln(tn2);
tn1:=tn2-101;
{ формирование указателя записи,
101 – это минимальное значение табельного номера }
seek(fout,tn1);
read(fout,zap);
s:=s+zap.zp;
writeln('ещё запрос? (y/ n)');
readln(ans);
until (ans = ‘n’);
writeln(‘s= ‘,s);
Close(fout)
End.
ВНИМАНИЕ: в задаче нет многих подстраховок: от ввода пустой строки, от несуществующего файла и др.