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

Вниз

Запись класса в TStream   Найти похожие ветки 

 
solomon ©   (2012-01-09 17:38) [0]

Есть класс

type
 TPostingClass = class
 private
 protected
 public
   ProjectName: string[255];
   ProjectMode:
   AccountsName: tstringlist;

   constructor Create;
 end;

constructor TPostingClass.Create;
begin
AccountsName:=tstringlist.Create;
end;

Создаем несколько экземпляров класса, заполняем их данными и записываем в поток TasksStream: TMemoryStream являющийся глобальной переменной:

var
p:TPostingClass;
begin
p:=TPostingClass.Create;
p.ProjectName:="первый аккаунт";
p.SourceType:=1;
p.AccountsName.Add("1 акк");
TasksStream.WriteBuffer(P, SizeOf(TPostingClass));
p.Free;

p:=TPostingClass.Create;
p.ProjectName:="второй аккаунт";
p.SourceType:=1;
p.AccountsName.Add("1 акк");
p.AccountsName.Add("2 акк");
TasksStream.WriteBuffer(P, SizeOf(TPostingClass));
p.Free;

p:=TPostingClass.Create;
p.ProjectName:="третий аккаунт";
p.SourceType:=1;
p.AccountsName.Add("1 акк");
p.AccountsName.Add("2 акк");
p.AccountsName.Add("3 акк");
TasksStream.WriteBuffer(P, SizeOf(TPostingClass));
p.Free;

Читаем данные из стрима:
Memo1.Clear;
TasksStream.Position:=0;

for k:=1 to 3 do
begin
   p:=TPostingClass.Create;
   TasksStream.ReadBuffer(P, SizeOf(TPostingClass));
   memo1.Lines.Add("ProjectName= "+p.ProjectName);
   memo1.Lines.Add("ProjectMode= "+inttostr(p.ProjectMode));

   for i:=0 to p.AccountsName.Count-1 do
    memo1.Lines.Add("AccountsName="+p.AccountsName.strings[i]);

   p.Free;
                                     
 memo1.Lines.Add("---");
end;

В итоге в Memo1 получаю

ProjectName=
ProjectMode= 0
---
ProjectName=
ProjectMode= 0
---
ProjectName=
ProjectMode= 0
---

не пойму в чем дело?


 
solomon ©   (2012-01-09 17:41) [1]

Прикол в том, что если при чтении данных из стрима строчки
p:=TPostingClass.Create;
и
p.free

убрать, то получаем в Memo1:

ProjectName= 
ProjectMode= 0
AccountsName= 1 акк
AccountsName= 2 акк
AccountsName= 3 акк
---
ProjectName= 
ProjectMode= 0
AccountsName= 1 акк
AccountsName= 2 акк
AccountsName= 3 акк
---
ProjectName= 
ProjectMode= 0
AccountsName= 1 акк
AccountsName= 2 акк
AccountsName= 3 акк
---

вообще не ясно почему в данном случае не вылезло AV на строке TasksStream.ReadBuffer(P, SizeOf(TPostingClass)); ведь объект P то не создан


 
DVM ©   (2012-01-09 18:57) [2]


> вообще не ясно почему в данном случае не вылезло AV на строке
> TasksStream.ReadBuffer(P, SizeOf(TPostingClass)); ведь объект
> P то не создан

потому и вылезло, что не создан, что же еще ждать при обращении по левому указателю.


 
solomon ©   (2012-01-09 19:28) [3]

DVM вы не внимательно читали, я написал что AV НЕ вылезло, меня это и удивило.

Но вопрос в другом, почему класс не сохраняется в стрим, ну или если сохраняется то не читается из него корректно?


 
~AQUARIUS~   (2012-01-09 19:36) [4]

Сделайте ShowMessage(IntToStr(SizeOf(TPostingClass))) и вы удивитесь еще больше.
А вообще, ничего странного в вашем случае нет. Потому что переменная p - это не обьект класса TPostingClass, а указатель на такой обьект. Т.е. вы в стрим записываете не поля, а указатели, которые после чтения в общем случае не имеют смысла


 
solomon ©   (2012-01-09 19:44) [5]

Ничего не понимаю, почему же P это не объект класса TPostingClass, я ведь его  не описывал как указатель то ?

Ладно пусть будет даже указателем, но как мне решить проблему, как записать и считать класс из стрима?


 
~AQUARIUS~   (2012-01-09 19:58) [6]

А и не надо описывать. Дельфи - не С++, там все такие переменные - указатели.
Если по-правильному, ваш класс должен иметь методы для сохранения и записи - типа LoadFromStream, SaveToStream, как большинство обьектов VCL/RTL. Эти методы и должны выполнять всю работу. Можно сделать их виртуальными и перекрывать в наследниках. Записывать обьект в бинарном виде (разименовав р) тоже нельзя - там есть еще служебные поля - указатель на метакласс и в новых версиях - указатель на монитор. После чтения эти указатели тоже будут невалидными


 
DVM ©   (2012-01-09 19:59) [7]


>  но как мне решить проблему, как записать и считать класс
> из стрима?
>
>

TWriter + TReader


 
~AQUARIUS~   (2012-01-09 20:02) [8]

DVM

А они разве запишут не-published поля?


 
DVM ©   (2012-01-09 20:04) [9]


> ~AQUARIUS~   (09.01.12 20:02) [8]


> А они разве запишут не-published поля?

Сами по себе они вообще ничего не запишут, сами пишем нужные поля в нужном порядке, сами и считываем в нужном порядке. Сами и префикс класса назначаем.


 
DVM ©   (2012-01-09 20:07) [10]

У меня большинство классов вот от такого унаследованы, в потомках надо определить ReadData и WriteData:


 TBaseStreamedObject = class(TPersistent)
 strict protected
   procedure ReadData(Reader : TReader); virtual; abstract;
   procedure WriteData(Writer : TWriter); virtual; abstract;
   procedure SaveToStream(Stream : TStream); virtual; abstract;
   procedure LoadFromStream(Stream : TStream); virtual; abstract;
   procedure SaveToFile(FileName : string); virtual; abstract;
   procedure LoadFromFile(FileName : string); virtual; abstract;
 end;

 TStreamedObject = class(TBaseStreamedObject)
 public
   procedure SaveToStream(Stream : TStream); override;
   procedure LoadFromStream(Stream : TStream); override;
   procedure SaveToFile(FileName : string); override;
   procedure LoadFromFile(FileName : string); override;
 end;

....

procedure TStreamedObject.LoadFromStream(Stream: TStream);
var
 Reader: TReader;
begin
 Reader := TReader.Create(Stream, $FF);
 try
   ReadData(Reader);
 finally
   FreeAndNil(Reader);
 end;
end;

//------------------------------------------------------------------------------

procedure TStreamedObject.SaveToStream(Stream: TStream);
var
 Writer: TWriter;
begin
 Writer := TWriter.Create(Stream, $FF);
 try
   WriteData(Writer);
 finally
   FreeAndNil(Writer);
 end;
end;

//------------------------------------------------------------------------------

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

//------------------------------------------------------------------------------

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


 
DVM ©   (2012-01-09 20:09) [11]

например:


procedure TSCMBaseAgentInfo.ReadData(Reader : TReader);
begin
 inherited;
 with Reader do
   begin
     FAgentUniqueID := ReadInteger;
     FAgentName := ReadString;
     Read(FAgentType, SizeOf(TSCMAgentType));
     FAgentVersion := ReadString;
   end;
end;

//------------------------------------------------------------------------------

procedure TSCMBaseAgentInfo.WriteData(Writer : TWriter);
begin
 inherited;
 with Writer do
 begin
   WriteInteger(FAgentUniqueID);
   WriteString(FAgentName);
   Write(FAgentType, SizeOf(TSCMAgentType));
   WriteString(FAgentVersion);
 end;
end;



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

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

Наверх




Память: 0.48 MB
Время: 0.003 c
3-1298974464
Очень злой
2011-03-01 13:14
2014.06.22
не могу создать AdoConnection в потоке


15-1378911726
p
2013-09-11 19:02
2014.06.22
RAD Studio XE5


15-1386177106
Rouse_
2013-12-04 21:11
2014.06.22
Задачка (ветка похоже будет долгой :)


15-1386058324
LDV
2013-12-03 12:12
2014.06.22
html-редактор


15-1386680638
Sergey Masloff
2013-12-10 17:03
2014.06.22
Есть знатоки SVN?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский