Королевство Дельфи"Knowledge itself is power"
F.Bacon
 Лицей
  
Главная
О лицее

Список семинаров

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  06:05[Войти] | [Зарегистрироваться]

Работа с файлами Паскаля - Типизированные файлы

Anatoly Podgoretsky
дата публикации 15-09-2003 13:34

урок из цикла: Уроки от АП


предыдущий урок содержание семинара следующий урок

Работа с файлами Паскаля - Типизированные файлы

Второй тип файлов, для которого нет поддержки в OS и VCL – это типизированные файлы. Это такой вид файлов, в котором содержатся записи одного типа и фиксированной длины. Часто используется или для организации мини баз, конфигураций, иногда для импорта/экспорта в специальных форматах. Работа с такими файлами не сложнее, чем работа с текстовыми файлами, наряду с освоенными методами добавляется только одно новое свойство. Если текстовые файлы чисто последовательные, то в типизированных файлах можно перемещаться на любую запись и затем производить последовательное чтение или запись. Это очень похоже на работу с TFileStream за одним исключением, единицей информации является не байт, а тип.

Типизированный файл определяется следующим образом
var
  FileVar: file of тип;

Где тип это или предопределенный или пользовательский типы. В качестве типов не могут фигурировать динамические структуры, такие как динамические массивы, длинные строки или любые указатели, поскольку все записи должны быть одинаковой длины и не должны указывать на внешние данные. Для обработки таких данных надо использовать не типизированные файлы.

Наряду с ранее указанными процедурами нам надо знать еще об некоторых функциях, это процедура Seek, которая не применима для текстовых файлов, а для типизированных файлов используется для перемещения указателя на нужную запись.

Для определения количества записей в файле можно использовать функцию FileSize, которая возвращает именно количество записей, а не длину файла, как это следует из ее названия.

Для определения текущей позиции в файле можно использовать функцию FilePos.

Для уменьшения длины файла можно использовать процедуру Truncate, которая обрезает файл по текущей позиции

Замечания по поводу открытия файлов, для этого используются две ранее описанные процедуры: Rewrite - создает новый файл для чтения/записи, если такой файл существует, его длина устанавливается в ноль, а Reset - открывает файл для чтения/записи и не изменяет его длины. Сразу видно различие в этих процедурах по отношению к текстовым файлам.

Примечание: записи считаются с нуля Для примеров возьмем любимую в ранних книгах по Паскалю, где в качестве примера использовался пример реализации телефонного справочника с помощью типизированных файлов или же подобные примеры для хранения персональных записей. Эту основу мы будем использовать и в других главах. Для этого определим следующий тип:
 
type
  TPhoneRec = packed record
    PersonName: string<25>;
    Address:    string<25>;
    Phone:      string<16>;
  end;

Теперь переходим к демонстрационному примеру, определения типа повторять не будем. Напишем только основные функции работы с файлом, а визуализацию самих данных оставим за бортом, но для самой визуализации очень хорошо подходит TStringGrid.

Примеры работы с типизированными файлами

// опредение глобальных для модуля или программы переменных
var
  PersonFile: file of TPhoneRec; // определили файл нашего типа
  DbOpen: Boolean;               // флаг состояния базы
  PhonesCount: Integer;          // количество записей в базе

// открытие базы и нициализация
// не пытаться работать с базой если результат = FALSE
function OpenDB(const DbName: string): Boolean;
begin
  AssignFile(PersonFile, DbName);
  try
    Reset(PersonFile);            // открываем базу
    PhonesCount := FileSize(PersonFile); // текущее кол. записей
    DbOpen := TRUE;               // открытие прошло нормально
  except
    PhonesCount := 0;
    DbOpen := FALSE;
  end;
  Result := DbOpen;
end;

// создание новой базы и инициализация
// не пытаться работать с базой если результат = FALSE
function CreateDB(const DbName: string): Boolean;
begin
  AssignFile(PersonFile, DbName);
  try
    Rewrite(PersonFile);        // открываем базу
    DbOpen := TRUE;             // открытие прошло нормально
  except
    DbOpen := FALSE;
  end;
  PhonesCount := 0;             // записей нет
  Result := DbOpen;
end;

// закрытие базы
procedure CloseDB;
begin
  if DbOpen
  then
    CloseFile(PersonFile);
end;

// Удалить все после указанной записи
procedure TruncateDB(const RecNo: Integer);
begin
  Seek(PersonFile, RecNo);
  Truncate(PersonFile);
end;

// Читать следующую запись
function ReadNextRec: TPhoneRec;
begin
  Read(PersonFile, Result);
end;

// Читать указанную запись
function ReadRec(const RecNo: Integer): TPhoneRec;
begin
  Seek(PersonFile, RecNo);
  Result := ReadNextRec;
end;

// изменить текущую запись
procedure ModifyNextRec(const Rec: TPhoneRec);
begin
  Write(PersonFile, Rec);
end;

// изменить указанную запись
procedure ModifyRec(const RecNo: Integer; const Rec: TPhoneRec);
begin
  Seek(PersonFile, RecNo);
  ModifyNextRec(Rec);
end;

// Добавить новую запись в конец файла
procedure AddRec(const Rec: TPhoneRec);
begin
  Seek(PersonFile,  PhonesCount); // переместиться на последнею запись
  ModifyNextRec(Rec);             // и добавить запись
  PhonesCount := FileSize(PersonFile);  // новое кол. записей
end;

Попробуем воспользоваться написанными функциями и для этого попробуем загрузить все записи в динамический массив.

program ReadPhoneBook;

{$APPTYPE CONSOLE}

uses
  PhoneDb;
var
  I: Integer;
  PhoneEntry: TPhoneRec;                   // отдельная запись
  PhoneBook: array of TPhoneRec;           // телефонный справояник
begin
  if not CreateDB('C:\DB\Phones.dbf') then Exit;
  WriteLn('Created C:\DB\Phones.dbf');
  for I := 0 to 3 do
  begin
    PhoneEntry.PersonName := 'PersonName ' + IntToStr(I);
    PhoneEntry.Address := 'Address ' + IntToStr(I);
    PhoneEntry.Phone := '(012) 3456789-' + IntToStr(I);
    AddRec(PhoneEntry);
    WriteLn(PhoneEntry.PersonName,' ',
            PhoneEntry.Address,' ' ,
            PhoneEntry.Phone);
  end;
  CloseDB;

  WriteLn('Check database');
  if OpenDB('C:\DB\Phones.dbf')
  then
  begin
    SetLength(PhoneBook, PhonesCount);
    for I := 0 to PhonesCount - 1 do
    begin
      PhoneBook := ReadNextRec;
      WriteLn(PhoneBook.PersonName,' ',
              PhoneBook.Address,' ' ,
              PhoneBook.Phone);
    end;
  end;
  WriteLn('Press ENTER to exit');
  ReadLn;
end.

Конечно, вместо использования процедур и функций, лучше это оформить в виде классов и иметь все преимущество от использования ООП, но в учебных целях это сделано именно так.
предыдущий урок содержание семинара следующий урок




Смотрите также материалы по темам:
[Записи, типизированные файлы ]

 Обсуждение материала [ 10-02-2009 03:36 ] 4 сообщения
  
Время на сайте: GMT минус 5 часов

Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
Функция может не работать в некоторых версиях броузеров.

Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

 
© При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
Все используемые на сайте торговые марки являются собственностью их производителей.

Яндекс цитирования