New Page 1
Delphi:
как сериализовать строку в поток (Stream,
string, WriteBuffer, ReadBuffer, Serialize)
В Delphi нельзя
напрямую сериализовать строку (String) в поток. В
частности, такой код работать не будет:
procedure
TEasyGameContainer.Serialize(AStream:TStream);
var i,cn:integer; lClassName:string;
begin
inherited Serialize(AStream);
cn:=FObjects.Count-1;
AStream.Write(cn,sizeof(cn));
for i:=0 to cn do
begin
lClassName:=TEasyGameObject(FObjects[i]).ClassName;
AStream.Write(lClassName,sizeof(lClassName));
TEasyGameObject(FObjects[i]).Serialize(AStream);
end;
end;procedure
TEasyGameContainer.Unserialize(AStream:TStream);
var i,cn:integer; lClassName:string;
lClass:TPersistentClass;
lObject:TPersistent;
begin
inherited
Unserialize(AStream);
AStream.Read(cn,sizeof(cn));
for i:=0 to cn do
begin
AStream.Read(lClassName,sizeof(lClassName));
lClass:=FindClass(lClassName);
lObject:=lClass.Create;
TEasyGameObject(lObject).Unserialize(AStream);
AddGameObject(TEasyGameObject(lObject));
end;
end; |
так как команда
AStream.Read(lClassName,sizeof(lClassName))
прочитает в
переменную "мусор". Все дело в том, что при выполнении команды
AStream.Write(lClassName,sizeof(lClassName));
в поток пишется не сама строка, а только 4-байта ее адреса.
При чтении так же читаются эти самые 4 байта. А куда потом будет указывать этот
адрес - неизвестно, но явное не на той текст строки, который мы хотели записать
в поток.
Что же делать? Правильно писать строку в поток и
считывать ее оттуда так:
procedure SerializeString(AString:string;
AStream:TStream);
var l:integer;
begin
l:=Length(AString);
AStream.Write(l,Sizeof(l));
if l>0 then
AStream.WriteBuffer(AString[1],l);
end;
function UnserializeString(AStream:TStream):string;
var l:integer; s:string;
begin
AStream.Read(l,Sizeof(l));
if l>0 then
begin
SetLength(s,L);
AStream.ReadBuffer(s[1],L);
end;
Result:=s;
end; |
Объявив эту процедуру и функцию, мы можем переделать
неработающий код:
procedure
TEasyGameContainer.Serialize(AStream:TStream);
var i,cn:integer; lClassName:string;
begin
inherited Serialize(AStream);
cn:=FObjects.Count-1;
AStream.Write(cn,sizeof(cn));
for i:=0 to cn do
begin
lClassName:=TEasyGameObject(FObjects[i]).ClassName;
SerializeString(lClassName,AStream);
TEasyGameObject(FObjects[i]).Serialize(AStream);
end;
end;
procedure TEasyGameContainer.Unserialize(AStream:TStream);
var i,cn:integer; lClassName:string;
lClass:TPersistentClass;
lObject:TPersistent;
begin
inherited
Unserialize(AStream);
AStream.Read(cn,sizeof(cn));
for i:=0 to cn do
begin
lClassName:=UnserializeString(AStream);
lClass:=FindClass(lClassName);
lObject:=lClass.Create;
TEasyGameObject(lObject).Unserialize(AStream);
AddGameObject(TEasyGameObject(lObject));
end;
end; |
|