Страница 1 из 1

Сохранение объекта в файл

Добавлено: 10 ноя 2006, 15:02
Фоб
Имеется список TList, хранящий указатели на объекты разного типа.

Нужно:
1. Сохранить объекты в файл
2. Загрузить объекты из файла и снова получить TList с указателями на эти объекты.

Как это сделать?

Добавлено: 11 ноя 2006, 13:49
vunder
Обо всем по-порядку.
1) Чтобы сохранить объект в файл (поток) лучше всего прибегнуть к стандартным средствам. У класса TComponent есть методы SaveToFile (SaveToStream) и LoadFromFile (LoadFromStream). А посему свои классы нужно наследовать от TComponent.
2) По-поводу TList. Здесь получается несколько сложнее, т.к. это один из классов нижнего уровня, поэтому он нифига не умеет. Поэтому работу с сохранением/загрузкой его элементов придется реализовывать самому.
Есть еще один вариант - тот же TComponent. У него есть метод InstertComponent и свойство Components. Это можно использовать как список объектов

Добавлено: 11 ноя 2006, 17:34
Фоб
Большое спасибо! И как я сам не додумался!
Только вышло несколько по-другому:
Создаю, для примера, класс:

Код: Выделить всё

Ta = class (TComponent)
  public
    x: integer;
    constructor Create;
  end;
Записываю экземпляр в поток:

Код: Выделить всё

procedure TForm1.Button1Click(Sender: TObject);
var
  b: Ta;
  s: TMemoryStream;
begin
  b:=Ta.create;
  s:=TMemoryStream.create;
  s.WriteComponent(b);
end;
Записывается.
Тогда как запись:

Код: Выделить всё

procedure TForm1.Button1Click(Sender: TObject);
var
  b: Ta;
  s: TMemoryStream;
begin
  b:=Ta.create;
  s:=TMemoryStream.create;
  b.saveToStream(s);
end;
Даёт при компиляции ошибку

Код: Выделить всё

Undeclared identifier "saveToStream"
У экземпляра отутствует этот метод. В дельфёвом хэлпе в списке методов класса TComponent saveToStream также отсутствует.

Вопросы:
1. Почему? В TComponent точно есть saveToStream? Как его добыть? Может я класс неверно объявляю?

2. Вот такая вещь:

Код: Выделить всё

s.WriteComponent(b);
s.Position:=0;
s.ReadComponent(b);
собственно, пишет всё и читает адекватно?

3. В моих реальных объектах широко налажена ссылочность через указатели (типа pointer)...
Я пока не пробовал, но думается, что после сохранения и загрузки, пойнтеры эти будут указывать отнюдь не на мои объектики, так ведь? Может есть способ как-то сохранить пойнтеровую ссылочность при сохранении-загрузке?

Добавлено: 12 ноя 2006, 11:53
vunder
Сори. На счет методов я погорячился.
чтение:

Код: Выделить всё

function ReadEx(Instance: TComponent; Stream: TStream; LeaveName: Boolean=False): TComponent;
begin
  with TReader.Create(Stream, 4096) do
  try
    if Assigned(Instance) and not LeaveName then Instance.Name := '';
    Result := ReadRootComponent(Instance)
  finally
    Free
  end
end;
запись:

Код: Выделить всё

function SaveToStream(Instance: TComponent; Stream: TStream): Boolean;
begin
  Result := True;
  Stream.WriteDescendent(Instance, nil);
end;
несколько советов:
1) для сохранения свойств они ОБЯЗАТЕЛЬНО д.б. в секции published
2) читай справку, там все есть

Добавлено: 15 ноя 2006, 19:33
Фоб
Спасибо, всё работает.

А есть ли способ сохранять и загружать любой объект, не являющийся наследником TComponent?

То есть, чтоб происходило следующее:
Имеем экземпляр объекта - участок памяти. Берём и копируем этот участок как есть в файл. А потом, при загрузке, снова распологаем в память. Можно так?

Добавлено: 16 ноя 2006, 11:49
vunder
в общем случае - нет.
объект это не статическая запись, у него есть много различных ссылок, недоступных пользователю