====== Операции над типизированными файлами в Турбо Паскале ======
Типизированные файлы называются таковыми потому, что для них определён тип данных записи. В них все записи являются одного типа (иными словами, однородными), т.е. **file of тип_данных**. Такие файлы содержат информацию в бинарном виде и (нормальный) человек прочесть их не сможет. Типом данных может быть любой тип данных Паскаля за исключением типа **file**.
Рассмотрим на примере тип **запись** (record). Тип запись определяется заранее (уже известен).
Например:
type
TInfoRecord = record { Определяем тип записи TInfoRecord }
Num: integer; { порядковый номер, числовой тип integer }
Name: string[20]; { Имя, до 20 символов }
Tel: string[12]; { Телефон, до 12 символов }
end;
Позиция при открытии (существующего) файла:
|*|0|1|2|3|4|
В файле может ещё не быть записей, если он едва был создан.
Не забывайте, что нумерация записей начинается **с нуля**.
===== Поиск записи =====
Алгоритм:\\
- установить позицию на начало, если необходимо (не нужно когда только что открыли файл для чтения)
- проверять каждую запись по нужному критерию (имя, телефон и т.д.)
- продолжать с пункта 2 пока не конец файла.
Пока не конец файла
Считать запись
Проверить, искомая ли. Если да, то что-то делать (вывести на экран, к примеру).
конец цикла
===== Добавление записи =====
Чтобы добавить запись в файл, необходимо сначала установить позицию в конец файла командой Seek ,а затем производить запись с помощью Write.
Позиция в конце файла
|0|1|2|3|4|*|
Производим запись. Теперь добавилась ещё одна.
|0|1|2|3|4|5|*|
type
TStudentInfo = record
Name: string[30];
group: string[10];
Exams: array[1..5] of byte;
end;
var
F: file of TStudentInfo;
st: TStudentInfo;
i: integer;
begin
Assign (f, 'students.dat');
{$I-}
Reset (F); { попытка открыть файл }
{$I+}
if IOresult <> 0 then { при неудаче создаём пустой файл }
Rewrite (F);
Seek (F, FileSize (F)); { становимся в конец файла }
With st do { заполняем данные записи }
begin
write ('Имя студента: '); readln (Name);
write ('Группа: '); readln (group);
writeln ('Оценки по пяти экзаменам:');
for i := 1 to 5 do
readln (Exams[i]);
end;
Write (F, st); { записываем запись в файл }
Close (F);
end.
===== Правка записи =====
Чтобы **поправить** N-ю запись, надо стать на позицию этой записи с помощью //Seek (F, recN)//, а затем производить запись. Аналогично предыдущему примеру, только вместо //Seek (F, FileSize(F))// пишем //Seek (F, recN)//. При этом надо следить за тем, чтобы не возникло ошибки при введении несуществуещего номера записи, чтобы программа не завершилась с ошибкой.
|0|1|*|2|3|
Здесь курсор установлен на позиции 2, готовой для чтения и правки записи под номером 2.
После того, как изменили запись, позиция продвинулась вперёд.
type
TStudentInfo = record
Name: string[30];
group: string[10];
Exams: array[1..5] of byte;
end;
var
F: file of TStudentInfo;
st: TStudentInfo;
recN, i, MaxRecords: integer;
exists: boolean;
begin
Assign (f, 'students.dat');
{$I-}
Reset (F);
{$I+}
if IOresult <> 0 then
halt;
MaxRecords := FileSize(F);
if MaxRecords = 0 then
begin
writeln ('Записей нет!');
exit;
end;
repeat
write ('Введите номер записи для замены [0..', MaxRecords-1, ']: ');
readln (recN);
{$I-}
Seek (F, recN); { пытаемся установиться на нужную запись }
{$I+}
exists := (IOresult = 0) and (recN < MaxRecords); { признак успеха }
if Not exists then
writeln ('Вы ввели номер несуществующей записи! Попытайтесь снова.');
until exists;
With st do
begin
write ('Имя студента: '); readln (Name);
write ('Группа: '); readln (group);
writeln ('Введите оценки по 5 экзаменам:');
for i := 1 to 5 do
readln (Exams[i]);
end;
Write (F, st); { записываем запись в файл }
Close (F);
end.
===== Поиск и правка записи =====
Если надо найти запись и исправить ее, надо:
- установить позицию на начало, если необходимо (не надо когда только открыли файл для чтения)
- проверять каждую запись по нужному критерию (имя, телефон и т.д.)
- вернуться на одну позицию назад:\\ Seek(F,FilePos(F)-1), т.к. после чтения записи с файла позиция уже продвинулась на следующую;
- внести изменения в записи и затем производить запись в файл.
- продолжать с пункта 2 пока не конец файла.
type
TStudentInfo=record
Name: string[30];
Kurs: string[20];
Exams: array[1..5] of byte;
end;
var
f: file of TStudentInfo;
st: TStudentInfo;
who: string[30];
found: boolean;
begin
write('Кого ищем? ');
readln(who);
if who='' then exit;
assign(f,'students.dat');
{$I-}
reset(F);
{$I+}
found:=false;
if IOresult=0 then
with st do
while Not EOF(F) do
begin
read(F,st);
if name=who then { нашли такого/ую }
begin
write('Заменить на фамилию: ');
readln(name);
found:=true;
seek(F,FilePos(F)-1); { вернуться на 1 позицию обратно, т.е. на позицию того, что надо заменять }
write(f,st);
break; { убрать это, если известно, что таких несколько }
end;
end;
close(f);
if Not Found
then writeln(Who,' не найден. Ха-ха')
else writeln(Who,' найден и заменен.');
writeln(#13#10'Жми Enter');
readln;
end.
===== Удаление записи =====
==== Удаление последовательности записей ====
Для удаления (отсечения) последовательности записей, начиная с текущей позиции (можно установить с //Seek//), применяют процедуру //Truncate//.
Процедура Truncate( var f ) устанавливает в текущей позиции признак конца файла
и удаляет (стирает) все последующие блоки.
==== Удаление одной записи ====
Для удаления одной **неконечной** записи требуется воспользоваться созданием дополнительного файла, в который запишутся все записи, кроме заданной.
Записываем записи 0..i-1, пропускаем запись i, а потом дописываем записи i+1..N.
=== Другой способ (хитрый) ===
Скопировать последнюю запись на место i-й, а потом отсечь последнюю с помощью //Truncate//.
===== Вставка записи =====
Для вставки записи также требуется воспользоваться созданием дополнительного файла, в который запишутся все записи:
* сначала записи 1..i-1
* затем вставляемая запись
* затем записи i, .. N