Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2008.02.10;
Скачать: [xml.tar.bz2];

Вниз

TClassList.Add(pointerToTheObject);   Найти похожие ветки 

 
savyhinst ©   (2008-01-14 15:31) [0]

Здраствуйте.
Подскажите пожалуйста, как сохранить какой-либо объект в файл, например TClassList. Причём будет ли при этом орректно сохранено его содержимое и можно ли сохранить два и более объектов в один файл. Подскажите пожалуйста как.
Спасибо за внимание.


 
Сергей М. ©   (2008-01-14 15:34) [1]

ты вообще разницу между "класс" и "объект" понимаешь ?

Сдается мне - нет.


 
savyhinst ©   (2008-01-14 15:39) [2]

Понимаю. Могу объяснить своими словами.


 
savyhinst ©   (2008-01-14 15:41) [3]

если type TsmoeObj=object то можно к его св-вам обращаться без Create, а класс он всегда потомок TObject, он без Create вызывает AV


 
Плохиш ©   (2008-01-14 15:45) [4]


> savyhinst ©   (14.01.08 15:41) [3]
> если type TsmoeObj=object то можно к его св-вам обращаться
> без Create, а класс он всегда потомок TObject, он без Create
> вызывает AV

Рыдал...

Откройте орешник...


 
Palladin ©   (2008-01-14 15:47) [5]


> [3] savyhinst ©   (14.01.08 15:41)

эээ... ну ладно... вопрос моего детства

http://www.delphimaster.ru/cgi-bin/faq.pl?look=1&id=988619105&n=19


 
Ins ©   (2008-01-14 15:50) [6]


> если type TsmoeObj=object то можно к его св-вам обращаться
> без Create, а класс он всегда потомок TObject, он без Create
> вызывает AV


Нет. В данном случае, класс - это тип данных (TObject, TPersistent и т.д.), а объекты - это экземпляры данного класса.


 
Сергей М. ©   (2008-01-14 16:00) [7]


> savyhinst ©   (14.01.08 15:39) [2]


Почитай уж хоть какой-ниь букварь что ли ..


 
savyhinst ©   (2008-01-14 16:25) [8]

А что же с сохранением в файл?


 
Сергей М. ©   (2008-01-14 16:28) [9]


> что же с сохранением в файл?


Сохранение объекта есть сохранение его свойств.

При этом контейнер для хранения не важен - это м.б. файл, мусорное ведро, Луна, карман, шкатулка...


 
savyhinst ©   (2008-01-14 16:30) [10]

Спасибо. Это понятно. А как сохранить два объекта в один файл и потом их достать оттуда целыми?


 
savyhinst ©   (2008-01-14 16:30) [11]

Можно сохранить объект в TIniFile без прописывания этого вручную?


 
savyhinst ©   (2008-01-14 16:30) [12]

Можно сохранить объект в TIniFile без прописывания этого вручную?


 
Ins ©   (2008-01-14 16:34) [13]

Я для сериализации простых объектов (не потомков TComponent) когда-то написал для себя такие классы. Для большинства моих задач - вполне подходит. Использование - просто объявить свой класс потомком TRttiObject, записать в секцию published свойства, которые должны быть сохранены, и вызвать для экземпляра SaveToFile:

unit ExLists;

interface

uses Windows, Classes, SysUtils, Contnrs, TypInfo, Graphics;

const
 strInvalidSignature = "Неверная сигнатура";

type
 TNotifyType = (ntLoadComplete, ntSaveComplete);

 EInvalidSignature = class(Exception);
 
 // Элемент списка. Среда генерирует для него RTTI информацию
 // Сохраняет и читает из потока все Published свойства
 TRttiObject = class(TInterfacedPersistent, IStreamPersist)
 protected
   class function ClassSignature: String; virtual;
 public
   procedure SaveToStream(Stream: TStream);
   procedure LoadFromStream(Stream: TStream);
   procedure LoadFromFile(FileName: TFileName);
   procedure SaveToFile(FileName: TFileName);
   constructor Create; virtual;
 end;

 // Список классов-потомков TRttiObject. Классы элементов списка необходимо
 // регистрировать с помощью RegisterClass до первого обращения к методам
 // загрузки из потока
 TRttiList = class(TObjectList, IStreamPersist)
 protected
   function GetRttiObject(Index: Integer): TRttiObject;
   procedure SetRttiObject(Index: Integer; AItem: TRttiObject);
   function _AddRef: Integer; stdcall;
   function _Release: Integer; stdcall;
 public
   function QueryInterface(const IID: TGUID; out Obj):
     HResult; virtual; stdcall;
   function Add(AItem: TRttiObject): Integer;
   function Extract(AItem: TRttiObject): TRttiObject;
   function Remove(AItem: TRttiObject): Integer;
   function IndexOf(AItem: TRttiObject): Integer;
   function First: TRttiObject;
   function Last: TRttiObject;
   procedure Insert(Index: Integer; AItem: TRttiObject);
   procedure SaveToStream(Stream: TStream); dynamic;
   procedure LoadFromStream(Stream: TStream); dynamic;
   procedure SaveToFile(const FileName: TFileName); virtual;
   procedure LoadFromFile(const FileName: TFileName); virtual;
   property Items[Index: Integer]: TRttiObject read GetRttiObject write
     SetRttiObject; default;
 end;

 // Класс для асинхронной работы
 // Любые изменения в списке необходимо оформлять так:
 // MyList.BeginUpdate;
 // try
 //   DoSomething;
 // finally
 //   MyList.EndUpdate;
 // end;
 TAsyncRttiList = class(TRttiList)
 private
   FCriticalSection: TRTLCriticalSection;
   procedure WaitReleaseCriticalSection;
 protected
   // Оповещение об окончании сохранения/загрузки. Рекомендуется через
   // PostMessage
   procedure NotifyMainThread(NotifyType: TNotifyType); virtual; abstract;
 public
   constructor Create; virtual;
   destructor Destroy; override;
   procedure BeginUpdate;
   procedure EndUpdate;
   procedure AsyncLoadFromFile(const FileName: TFileName);
   procedure AsyncSaveToFile(const FileName: TFileName);
 end;

 TSaveLoadThread = class(TThread)
 private
   FListObj: TAsyncRttiList;
   FFileName: TFileName;
 public
   property ListObj: TAsyncRttiList read FListObj write FListObj;
   property FileName: TFileName read FFileName write FFileName;
 end;

 TSaveThread = class(TSaveLoadThread)
 protected
   procedure Execute; override;
 end;

 TLoadThread = class(TSaveLoadThread)
 protected
   procedure Execute; override;
 end;

 TRTTIObjectClass = class of TRTTIObject;



 
Ins ©   (2008-01-14 16:34) [14]

implementation

{ TRttiList }

function TRttiList.Add(AItem: TRttiObject): Integer;
begin
 Result := inherited Add(AItem);
end;

function TRttiList.Extract(AItem: TRttiObject): TRttiObject;
begin
 Result := TRttiObject(inherited Extract(AItem));
end;

function TRttiList.First: TRttiObject;
begin
 Result := TRttiObject(inherited First);
end;

function TRttiList.GeTRttiObject(Index: Integer): TRttiObject;
begin
 Result := TRttiObject(inherited Items[Index]);
end;

function TRttiList.IndexOf(AItem: TRttiObject): Integer;
begin
 Result := inherited IndexOf(AItem);
end;

procedure TRttiList.Insert(Index: Integer; AItem: TRttiObject);
begin
 inherited Insert(Index, AItem);
end;

function TRttiList.Last: TRttiObject;
begin
 Result := TRttiObject(inherited Last);
end;

procedure TRttiList.LoadFromFile(const FileName: TFileName);
var
 Stream: TFileStream;
begin
 Stream:=TFileStream.Create(FileName,fmOpenRead);
 try
   LoadFromStream(Stream);
 finally
   Stream.Free;
 end;
end;

procedure TRttiList.LoadFromStream(Stream: TStream);
var
 Cnt,Size,i: Integer;
 AClassName: String;
begin
 Clear;
 Stream.Read(Cnt,SizeOf(Integer));
 Capacity:=Cnt;
 for i:=0 to Cnt - 1 do begin
   Stream.Read(Size,SizeOf(Integer));
   SetLength(AClassName,Size);
   Stream.Read(PChar(AClassName)^,Size);
   Add(TRTTIObjectClass(FindClass(AClassName)).Create);
   Items[i].LoadFromStream(Stream);
 end;
end;

function TRttiList.QueryInterface(const IID: TGUID; out Obj): HResult;
const
 E_NOINTERFACE = HResult($80004002);
begin
 if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE;
end;

function TRttiList.Remove(AItem: TRttiObject): Integer;
begin
 Result := inherited Remove(AItem);
end;

procedure TRttiList.SaveToFile(const FileName: TFileName);
var
 Stream: TFileStream;
begin
 Stream:=TFileStream.Create(FileName,fmCreate);
 try
   SaveToStream(Stream);
 finally
   Stream.Free;
 end;
end;

procedure TRttiList.SaveToStream(Stream: TStream);
var
 Len,i: Integer;
 AClassName: String;
begin
 Stream.Write(Count,SizeOf(Integer));
 for i:=0 to Count - 1 do begin
   AClassName:=Items[i].ClassName;
   Len:=Length(AClassName);
   Stream.Write(Len,SizeOf(Integer));
   Stream.Write(PChar(AClassName)^,Len);
   Items[i].SaveToStream(Stream);
 end;
end;

procedure TRttiList.SeTRttiObject(Index: Integer; AItem: TRttiObject);
begin
 inherited Items[Index] := AItem;
end;

function TRttiList._AddRef: Integer;
begin
 Result := -1;
end;

function TRttiList._Release: Integer;
begin
 Result := -1;
end;

{ TRttiObject }

class function TRttiObject.ClassSignature: String;
begin
 Result:="";
end;

constructor TRttiObject.Create;
begin
 inherited Create;
end;

procedure TRttiObject.LoadFromFile(FileName: TFileName);
var
 Stream: TFileStream;
begin
 Stream:=TFileStream.Create(FileName,fmOpenRead);
 try
   LoadFromStream(Stream);
 finally
   Stream.Free;
 end;
end;



 
Ins ©   (2008-01-14 16:34) [15]

procedure TRttiObject.LoadFromStream(Stream: TStream);
var
 TypeData: PTypeData;
 PropList: PPropList;
 Count,i: Integer;

 function ReadSignature: Boolean;
 var
   Signature: String;
   L: Integer;
 begin
   L:=Length(ClassSignature);
   SetLength(Signature,L);
   Stream.Read(PChar(Signature)^,L);
   Result:=Signature = ClassSignature;
 end;

 procedure ReadOrdProp;
 var
   Value: Integer;
 begin
   Stream.Read(Value,SizeOf(Value));
   SetOrdProp(self,PropList[i],Value);
 end;

 procedure ReadFloatProp;
 var
   Value: Extended;
 begin
   Stream.Read(Value,SizeOf(Value));
   SetFloatProp(self,PropList[i],Value);
 end;

 procedure ReadStringProp;
 var
   Value: String;
   L: Integer;
 begin
   Stream.Read(L,SizeOf(L));
   SetLength(Value,L);
   Stream.Read(PChar(Value)^,L);
   SetStrProp(self,PropList[i],Value);
 end;

 procedure ReadClassProp;
 var
   Obj: TObject;
   SaveLoader: IStreamPersist;
   IsEmpty: Boolean;
 begin
   IsEmpty:=false;
   Obj:=GetObjectProp(self,PropList[i]);
   if (Obj is TGraphic) then begin
     Stream.Read(IsEmpty,SizeOf(Boolean));
   end;
   if (not IsEmpty) then begin
     if Supports(Obj,IStreamPersist,SaveLoader) then begin
       SaveLoader.LoadFromStream(Stream);
     end;
   end;
 end;
 
begin
 if ReadSignature then begin
   TypeData:=GetTypeData(ClassInfo);
   Count:=TypeData.PropCount;
   if Count>0 then begin
     GetMem(PropList,SizeOf(PPropInfo)*Count);
     try
       GetPropInfos(ClassInfo,PropList);
       for i:=0 to Count - 1 do begin
         case PropList[i].PropType^.Kind of
           tkEnumeration, tkInteger, tkChar, tkWChar: ReadOrdProp;
           tkFloat: ReadFloatProp;
           tkString, tkLString: ReadStringProp;
           tkClass: ReadClassProp;
         end;
       end;
     finally
       FreeMem(PropList,SizeOf(PPropInfo)*Count);
     end;
   end;
 end
 else begin
   // Неверная сигнатура
   raise EInvalidSignature.Create(ClassName+": "+strInvalidSignature);
 end;
end;

procedure TRttiObject.SaveToFile(FileName: TFileName);
var
 Stream: TFileStream;
begin
 Stream:=TFileStream.Create(FileName,fmCreate);
 try
   SaveToStream(Stream);
 finally
   Stream.Free;
 end;
end;

procedure TRttiObject.SaveToStream(Stream: TStream);
var
 TypeData: PTypeData;
 PropList: PPropList;
 Count,i: Integer;

 procedure WriteSignature;
 var
   Signature: String;
   L: Integer;
 begin
   Signature:=ClassSignature;
   L:=Length(Signature);
   Stream.Write(PChar(Signature)^,L);
 end;

 procedure WriteOrdProp;
 var
   Value: Integer;
 begin
   Value:=GetOrdProp(self,PropList[i]);
   Stream.Write(Value,SizeOf(Value));
 end;

 procedure WriteFloatProp;
 var
   Value: Extended;
 begin
   Value:=GetFloatProp(self,PropList[i]);
   Stream.Write(Value,SizeOf(Value));
 end;

 procedure WriteStringProp;
 var
   Value: String;
   L: Integer;
 begin
   Value:=GetStrProp(self,PropList[i]);
   L:=Length(Value);
   Stream.Write(L,SizeOf(L));
   Stream.Write(PChar(Value)^,Length(Value));
 end;

 procedure WriteClassProp;
 var
   Obj: TObject;
   SaveLoader: IStreamPersist;
   IsEmpty: Boolean;
 begin
   Obj:=GetObjectProp(self,PropList[i]);
   if (Obj is TGraphic) then begin
     IsEmpty:=TGraphic(Obj).Empty;
     Stream.Write(IsEmpty,SizeOf(Boolean));
   end;
   if Supports(Obj,IStreamPersist,SaveLoader) then begin
     SaveLoader.SaveToStream(Stream);
   end;
 end;

begin
 WriteSignature;
 TypeData:=GetTypeData(ClassInfo);
 Count:=TypeData.PropCount;
 if Count>0 then begin
   GetMem(PropList,SizeOf(PPropInfo)*Count);
   try
     GetPropInfos(ClassInfo,PropList);
     for i:=0 to Count - 1 do begin
       case PropList[i].PropType^.Kind of
         tkEnumeration, tkInteger, tkChar, tkWChar: WriteOrdProp;
         tkFloat: WriteFloatProp;
         tkString, tkLString: WriteStringProp;
         tkClass: WriteClassProp;
       end;
     end;
   finally
     FreeMem(PropList,SizeOf(PPropInfo)*Count);
   end;
 end;
end;

{ TAsyncRttiList }

procedure TAsyncRttiList.AsyncLoadFromFile(const FileName: TFileName);
var
 Thread: TLoadThread;
begin
 try
   Thread:=TLoadThread.Create(true);
   Thread.FreeOnTerminate:=true;
   Thread.ListObj:=self;
   Thread.FileName:=FileName;
   Thread.Resume;
 except
   // Ошибка потока
 end;
end;

procedure TAsyncRttiList.AsyncSaveToFile(const FileName: TFileName);
var
 Thread: TSaveThread;
begin
 try
   Thread:=TSaveThread.Create(true);
   Thread.FreeOnTerminate:=true;
   Thread.ListObj:=self;
   Thread.FileName:=FileName;
   Thread.Resume;
 except
   // Ошибка потока
 end;
end;

procedure TAsyncRttiList.BeginUpdate;
begin
 EnterCriticalSection(FCriticalSection);
end;

constructor TAsyncRttiList.Create;
begin
 inherited Create;
 InitializeCriticalSection(FCriticalSection);
end;

destructor TAsyncRttiList.Destroy;
begin
 WaitReleaseCriticalSection;
 DeleteCriticalSection(FCriticalSection);
 inherited Destroy;
end;

procedure TAsyncRttiList.EndUpdate;
begin
 LeaveCriticalSection(FCriticalSection);
end;

procedure TAsyncRttiList.WaitReleaseCriticalSection;
begin
 EnterCriticalSection(FCriticalSection);
 LeaveCriticalSection(FCriticalSection);
end;

{ TSaveThread }

procedure TSaveThread.Execute;
begin
 ListObj.BeginUpdate;
 try
   ListObj.SaveToFile(FFileName);
   ListObj.NotifyMainThread(ntSaveComplete);
 finally
   ListObj.EndUpdate;
 end;
end;

{ TLoadThread }

procedure TLoadThread.Execute;
begin
 ListObj.BeginUpdate;
 try
   ListObj.LoadFromFile(FFileName);
   ListObj.NotifyMainThread(ntLoadComplete);
 finally
   ListObj.EndUpdate;
 end;
end;

end.


 
savyhinst ©   (2008-01-14 16:47) [16]


> Ins

Крууто. Вот только в том и проблема что я не могу просто взять и объявить TGLFreeForm потомком чего-то. А мне именно его надобно сохранить.


 
Apollon ©   (2008-01-14 16:49) [17]

>Ins ©   (14.01.08 16:34) [13], [14], [15]

Сильно, но "Все уже украдено(написано) до нас" (с)

http://www.rsdn.ru/article/delphi/serialization.xml


 
Apollon ©   (2008-01-14 16:55) [18]


> Вот только в том и проблема что я не могу просто взять и
> объявить TGLFreeForm потомком чего-то. А мне именно его
> надобно сохранить.

Если твой класс не является наследником TPersistent или для него явно не указана директива о включении для него RTTI, то в автоматическом режиме ты его никак не сохранишь


 
Ins ©   (2008-01-14 16:57) [19]

TGLFreeForm - если это форма, то стандартная сериализация (TSteram.WriteComponent/ReadComponent) чем не подходит?


 
Сергей М. ©   (2008-01-14 17:01) [20]


> savyhinst ©   (14.01.08 16:47) [16]


Ты придурок или куда ?

Тебе же сказано - сохранение объекта есть ничто иное как сохранение свойств этого объекта.


 
Apollon ©   (2008-01-14 17:03) [21]


> TGLFreeForm - если это форма, то стандартная сериализация
> (TSteram.WriteComponent/ReadComponent) чем не подходит?


Если мне память не изменяет, это класс из библиотек GLScene, и он не является наследником TComponent.


 
Ins ©   (2008-01-14 17:07) [22]


> Если мне память не изменяет, это класс из библиотек GLScene,
>  и он не является наследником TComponent.


Ну тогда звиняйте, мне показалось (по названию), что это класс-потомок TForm. GLScene в глаза не видел :)


 
icWasya ©   (2008-01-14 17:07) [23]

Если класс скомпилировать с директивой {$M+}, то его свойства(published) будут доступны в рун-тиме


 
savyhinst ©   (2008-01-14 17:08) [24]


> Если мне память не изменяет, это класс из библиотек GLScene,
>  и он не является наследником TComponent.

Я щас посмотрел - он является наследникои TComponent. Только не прямо, а то что он наследует в свою очередь наследует ещё всякую дрянь, а она уже TComponent. Значит, можно сохранять WriteComponent?


 
Apollon ©   (2008-01-14 17:09) [25]


> savyhinst ©  


а вообще, друх, перед тем как пытаться создавать 3D приложения, неплохо было бы разобраться с азами...


 
Ins ©   (2008-01-14 17:10) [26]


> Apollon ©   (14.01.08 17:09) [25]


Не царское это дело :)


 
Apollon ©   (2008-01-14 17:10) [27]


> savyhinst ©   (14.01.08 17:08) [24]


значит, изменяет...
тогда смело используй WriteComponent


 
savyhinst ©   (2008-01-14 17:12) [28]


> тогда смело используй WriteComponent

Спасибо огромное. Буду пытаться реализовать.


 
Apollon ©   (2008-01-14 17:12) [29]


> Если класс скомпилировать с директивой {$M+}, то его свойства(published)
> будут доступны в рун-тиме

я это и имел в виду в [18] :)


 
Amoeba ©   (2008-01-14 17:14) [30]

http://rsdn.ru/article/delphi/serialization.xml



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2008.02.10;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.039 c
2-1200417720
сопляк
2008-01-15 20:22
2008.02.10
TToolBar - ошибка винды или VCL?


2-1200553424
vvrz
2008-01-17 10:03
2008.02.10
Как автоматически прописать ODBC и BDE


15-1199936235
Slider007
2008-01-10 06:37
2008.02.10
С днем рождения ! 10 января 2008 четверг


15-1199808776
VAD*Anti Gopn!k
2008-01-08 19:12
2008.02.10
NVIDIA 7600GS


15-1199546183
Сканер
2008-01-05 18:16
2008.02.10
Вас не раздражает когда "считывают" ?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский