Недавно добавленные исходники

•  DeLiKaTeS Tetris (Тетрис)  160

•  TDictionary Custom Sort  3 337

•  Fast Watermark Sources  3 088

•  3D Designer  4 847

•  Sik Screen Capture  3 342

•  Patch Maker  3 553

•  Айболит (remote control)  3 658

•  ListBox Drag & Drop  3 015

•  Доска для игры Реверси  81 697

•  Графические эффекты  3 945

•  Рисование по маске  3 249

•  Перетаскивание изображений  2 629

•  Canvas Drawing  2 752

•  Рисование Луны  2 580

•  Поворот изображения  2 189

•  Рисование стержней  2 168

•  Paint on Shape  1 568

•  Генератор кроссвордов  2 235

•  Головоломка Paletto  1 767

•  Теорема Монжа об окружностях  2 229

•  Пазл Numbrix  1 685

•  Заборы и коммивояжеры  2 057

•  Игра HIP  1 282

•  Игра Go (Го)  1 230

•  Симулятор лифта  1 475

•  Программа укладки плитки  1 216

•  Генератор лабиринта  1 548

•  Проверка числового ввода  1 366

•  HEX View  1 497

•  Физический маятник  1 358

 
скрыть


Delphi FAQ - Часто задаваемые вопросы

| Базы данных | Графика и Игры | Интернет и Сети | Компоненты и Классы | Мультимедиа |
| ОС и Железо | Программа и Интерфейс | Рабочий стол | Синтаксис | Технологии | Файловая система |



Delphi Sources

Сохранение и загрузка данных в объекты на примере коллекций



Если в Вашей программе используются классы для описания объектов некоторой предметной области, то данные, их инициализирующие, можно хранить и в базе данных. Но можно выбрать гораздо более продуктивный подход, который доступен в Delphi/C++ Builder. Среда разработки Delphi/C++ Builder хранит ресурсы всех форм в двоичных или текстовых файлах и эта возможность доступна и для разрабатываемых с ее помощью программ. В данном случае, для оценки удобств такого подхода лучше всего рассмотреть конкретный пример.

Необходимо реализовать хранение информации о некоей службе рассылки и ее подписчиках. Будем хранить данные о почтовом сервере и список подписчиков. Каждая запись о подписчике хранит его личные данные и адрес, а также список тем(или каталогов), на которые он подписан. Как большие поклонники Гради Буча (Grady Booch), а также будучи заинтересованы в удобной организации кода, мы организуем информацию о подписчиках в виде объектов. В Delphi для данной задачи идеально подходит класс TCollection, реализующий всю необходимую функциональность для работы со списками типизированных объектов. Для этого мы наследуемся от TCollection, называя новый класс TMailList, а также создаем наследника от TCollectionItem - TMailClient. Последний будет содержать все необходимые данные о подписчике, а также реализовывать необходимые функции для работы с ним.

Начнем с TMailClient.


type
  TMailClient = class(TCollectionItem)
  private
    FName: string;
    FAddress: string;
    FEnabled: boolean;
    FFolders: TStringList;
  public
    Files: TStringList;
    constructor Create(Collection: TCollection); override;
    destructor Destroy; override;
    procedure PickFiles;
  published
    property name: string read FName write FName;
    property Address: string read FAddress write FAddress;
    property Enabled: boolean read FEnabled write FEnabled default true;
    property Folders: TStringList read FFolders write FFolders;
  end;

Класс содержит сведения о имени клиента, его адресе, его статусе(Enabled), а также список каталогов, на которые он подписан. Процедура PickFiles составляет список файлов к отправке и сохраняет его в свойстве Files. Класс TMailList, хранящий объекты класса TMailClient, приведен ниже.


  TMailList = class(TCollection)
  public
   function GetMailClient(index: Integer): TMailClient;
   procedure SetMailClient(index: Integer; Value: TMailClient);
  public
   function Add: TMailClient;
   property Items[index: Integer]: TMailClient read GetMailClient
   write SetMailClient; default;
  end;

Теперь поместим класс TMailList в класс TMailer, содержащий также и данные о параметрах доступа к почтовому серверу для отправки почты.


  TMailer = class(TComponent)
  private
    name: string;
    EMail: string;
    FMailList: TMailList;
    FLastActivated: TDateTime;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property MailList: TMailList read FMailList write FMailList;
    property LastActivated: TDateTime read FLastActivated write FLastActivated;
  end;

В данном случае мы наследуемся от класса TComponent, для того, чтобы была возможности записи данных объекта в файл. Свойство MailList содержит уже объект класса TMailList, а свойство LastActivated - дату последнего запуска программы рассылки.

Реализация всех приведенных классов приведена ниже.


constructor TMailClient.Create(Collection: TCollection);
begin
  inherited;
  Folders := TStringList.Create;
  Files := TStringList.Create;
  FEnabled := true;
end;

destructor TMailClient.Destroy;
begin
  Folders.Free;
  Files.Free;
  inherited;
end;

procedure TMailClient.PickFiles;
var
  i: integer;
begin
  for i := 0 to Folders.Count - 1 do
    CreateFileList(Files, Folders[i]);
end;

function TMailList.GetMailClient(index: Integer): TMailClient;
begin
  Result := TMailClient(inherited Items[index]);
end;

procedure TMailList.SetMailClient(index: Integer; Value: TMailClient);
begin
  Items[index].Assign(Value);
end;

function TMailList.Add: TMailClient;
begin
  Result := TMailClient(inherited Add);
end;

constructor TMailer.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  MailList := TMailList.Create(TMailClient);
  FLastActivated := now;
end;

destructor TMailer.Destroy;
begin
  MailList.Free;
  inherited;
end;

Функция CreateFileList создает по каким-либо правилам список файлов на основе переданного ей списка каталогов, обходя их рекурсивно.


procedure CreateFileList(sl: TStringList; FilePath: string);
var
  sr: TSearchRec;

  procedure ProcessFile;
  begin
    if (sr.name = '.') or(sr.name = '..') then
      exit;
    if sr.Attr <> faDirectory then
      sl.Add(FilePath + '\' + sr.name);
    if sr.Attr = faDirectory then
      CreateFileList(sl, FilePath + '\' + sr.name);
  end;

begin
  if not DirectoryExists(FilePath) then
    exit;
  if FindFirst(FilePath + '\' + Settings.IncludeFileMasks,
  faAnyFile , sr) = 0 then
    ProcessFile;
  while FindNext(sr) = 0 do
    ProcessFile;
  FindClose(sr);
end;

В итоге мы располагаем классом TMailer, содержащим всю необходимую нам информацию. Теперь перейдем к созданию объекта, их сохранению и загрузке.


var
  sDataFile: string;
  MLN: TMailLateNight;
begin
  MLN := TMailLateNight.Create(nil);
  sDataFile := ExtractFilePath(ParamStr(0)) + 'users.dat';

  //...загрузка данных из файла
  if FileExists(sDatsFile) then
    LoadUsersFromTextFile(MLN, sDatsFile);

  ...

  //...работа с объектами
  for i:=0 to MLN.MailList.Count-1 do
  begin
    s := MLN.MailList[i].name;
    s := MLN.MailList[i].Address;

    MLN.MailList[i].PickFiles;

    for j:=0 to MLN.Files.Count-1 do
    begin
      s := MLN.MailList[i].Files[j];

      ...

      //...сохранение данных в файл
      SaveComponentToTextFile(MLN, sDataFile);

Хранение данных в файле позволяет оказаться от использования БД, если объем данных не слишком велик и нет необходимости в совместном доступе к данным.

Самое главное - мы организуем все данные в виде набора удобных для работы классов и не тратим время на их сохранение и инициализацию из БД.

Далее приведен код функций для сохранения/чтения компонента.


//...процедура удаляет все дочерние компоненты из формы
procedure DeleteComponents(Form: TForm);
var
  i: integer;
begin
  for i := Form.ComponentCount - 1 downto 0 do
    Form.Components[i].Free;
end;

// ...процедура загружает(инициализирует)
// компонент из текстового файла с ресурсом
procedure LoadComponentFromTextFile(Component: TComponent;
FileName: string);
var
  ms: TMemoryStream;
  fs: TFileStream;
begin
  ms := TMemoryStream.Create;
  fs := TFileStream.Create(FileName, fmOpenRead);
  try
    ObjectTextToBinary(fs, ms);
    ms.position := 0;
    ms.ReadComponent(Component);
  finally
    ms.Free;
    fs.free;
  end;
end;

//...процедура сохраняет компонент в текстовый файл
procedure SaveComponentToTextFile(Component: TComponent;
FileName: string);
var
  ms: TMemoryStream;
  fs: TFileStream;
begin
  fs := TFileStream.Create(FileName, fmCreate or fmOpenWrite);
  ms := TMemoryStream.Create;
  try
    ms.WriteComponent(Component);
    ms.position := 0;
    ObjectBinaryToText(ms, fs);
  finally
    ms.Free;
    fs.free;
  end;
end;





Похожие по теме исходники

Экспорт баз данных в Excel

База данных "Книжный магазин"

База данных Видеофильмов

База данных "Школа"

 

База данных без BDE

База данных студентов

Фильтрование данных

Pevrica (сжатие данных)

 



Copyright © 2004-2024 "Delphi Sources" by BrokenByte Software. Delphi World FAQ

Группа ВКонтакте