Типизированные файлы называются таковыми потому, что для них определён тип данных записи. В них все записи являются одного типа (иными словами, однородными), т.е. 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 |
В файле может ещё не быть записей, если он едва был создан.
Не забывайте, что нумерация записей начинается с нуля.
Алгоритм:
Пока не конец файла Считать запись Проверить, искомая ли. Если да, то что-то делать (вывести на экран, к примеру). конец цикла
Чтобы добавить запись в файл, необходимо сначала установить позицию в конец файла командой 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.
Если надо найти запись и исправить ее, надо:
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.
Для вставки записи также требуется воспользоваться созданием дополнительного файла, в который запишутся все записи: