Форум: "Основная";
Текущий архив: 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