Текущий архив: 2005.07.11;
Скачать: CL | DM;
ВнизЗапись/восстановление TComponent из строки. Найти похожие ветки
← →
w666w (2005-06-13 14:37) [0]Добрый день.
Есть необходимость передавать компонент для хранения в базе данных в инете. И соответсвенно восстанавливать из этой базы.
Для этого надо соответсвенно "срез" этого компонента каким-то обазом превратить в строку. Без проблем можно это сделать, записав предварительно его методом WriteComponentResFile в файл, потом прочесть весь файл в строку и после этого уже передавать. Но надо без файла и этих лишних движений. Соответственно надо и восстанавливать обратно из строки в компонент.
Помогите пожалуйста. За пример кода буду очень благодарен.
← →
Stanislav © (2005-06-13 14:47) [1]TMemoryStream и Blob поля в базе.
← →
w666w (2005-06-13 14:53) [2]Насчет базы нет проблем. Насколько понимаю записать компонент в поток:
procedure Save_struct(var _t:TComponent);
var _M: TMemoryStream;
begin
_M := TMemoryStream.Create;
Try
_M.WriteBuffer( _t, sizeof(_t) );
_M.
_M.SaveToFile(êóäà);
finally
_M.Free;
end;
end;
Поправьте если не так.
А как из TMemoryStream в строку забрать?
← →
w666w (2005-06-13 14:54) [3]Неверно код написал.
procedure Save_struct(var _t:TComponent);
var _M: TMemoryStream;
begin
_M := TMemoryStream.Create;
Try
_M.WriteBuffer( _t, sizeof(_t) );
finally
_M.Free;
end;
end;
← →
Stanislav © (2005-06-13 15:01) [4]А зачем в строку?
procedure Save_struct(var _t:TComponent);
var _M: TMemoryStream;
begin
_M := TMemoryStream.Create;
Try
_M.WriteBuffer( _t, sizeof(_t) );
_M.Position:=0;
TBlobField(MyField).LoadFromStream(_M);
finally
_M.Free;
end;
end;
← →
w666w (2005-06-13 15:05) [5]База находитя на удаленном хосте (в инете). Туда надо передавать срез компонента в каком-то виде. Архив, текст... как угодно назовите... Но главная задача - не создавать файлы на диске перед отправкой. И соотв. после скачки из удаленной базы перед восстановлением компонента тоже файлов не создавать.
Вот такая вот задачка...
← →
Stanislav © (2005-06-13 15:08) [6]Stanislav © (13.06.05 15:01) [4]
Так файл и не будет создаваться. Вы считываете в поток, а потом поток прямо в базу, как в примере:
procedure Save_struct(var _t:TComponent);
var _M: TMemoryStream;
begin
_M := TMemoryStream.Create;
Try
_M.WriteBuffer( _t, sizeof(_t) );
_M.Position:=0;
TBlobField(MyField).LoadFromStream(_M);
finally
_M.Free;
end;
end;
← →
w666w (2005-06-13 15:36) [7]На сервере идет аутентификация пользователя, после успешной - запись/чтение из blob поля и передача обратно либо кода успешного сохранения, либо непосредственно кода компонента. Просто напрямую с базой работать нельзя, таковы условия задачи. Поэтому прийдется соединяться по HTTP и проводить много разных манипуляций которые здесь не имеет значения описывать.
Итог: нужно иметь в распоряжении строку, которую постом подцеплять к HTTP соединению. То есть надо реализовать что-то типа:
function GetComponentString(aComponent : TComponent) : string;
var fResult : string;
_M: TMemoryStream;
begin
fResult := "";
_M := TMemoryStream.Create;
try
_M.WriteBuffer(aComponent, sizeof(aComponent));
fResult := .............
finally
_M.Free;
end;
Result := fResult;
end;
Вот прошу помочь с моментом
fResult := ..........
Ну и соотв. Обратная процедура восстановления космонента из строки, которая вернется по HTTP.
← →
Просто Джо © (2005-06-13 15:51) [8]Можно сделать таким образом:
function GetComponentString (AComponent: TComponent): string;
var
AStream: TMemoryStream;
AStrStream: TStringStream;
begin
Result := "";
AStrStream := TStringStream.Create("");
try
AStream := TMemoryStream.Create;
try
AStream.WriteComponent(AComponent);
AStream.Seek(0,soFromBeginning);
ObjectBinaryToText(AStream,AStrStream);
finally
AStream.Free;
end;
Result := AStrStream.DataString;
finally
AStrStream.Free
end;
end;
← →
Stanislav © (2005-06-13 15:57) [9]Если содержание строки не имеет смысла, то в принципе, тот же поток можно отобразить в виде строки.
Например:
function GetComponentString(aComponent : TComponent) : string;
var fResult : string; MM:TMemo;
_M: TMemoryStream;
begin
fResult := "";
_M := TMemoryStream.Create;
MM:=TMemo.Create(Self);
try
_M.WriteBuffer(aComponent, sizeof(aComponent));
_M.Position:=0;
MM.LoadFromStream(_M);
fResult := MM.text;
finally
MM.Free
_M.Free;
end;
Result := fResult;
end;
Для удобства я привел пример с MEMO, но вообще можно результат потока считать прямо в строку.
← →
Stanislav © (2005-06-13 15:59) [10]Stanislav © (13.06.05 15:57) [9]
>Если содержание строки не имеет смысла...
Имел ввиду визуального :-)
← →
Просто Джо © (2005-06-13 15:59) [11]Дополнение к [8] Просто Джо © (13.06.05 15:51)
А вот так обратное преобразование:
procedure LoadComponentFromString (AComponent: TComponent; AString: string);
var
AStream: TMemoryStream;
AStrStream: TStringStream;
begin
AStrStream := TStringStream.Create(AString);
try
AStream := TMemoryStream.Create;
try
ObjectTextToBinary(AStrStream,AStream);
AStream.Seek(0,soFromBeginning);
AStream.ReadComponent(AComponent);
finally
AStream.Free;
end;
finally
AStrStream.Free
end;
end;
← →
Просто Джо © (2005-06-13 16:05) [12]Примечание к моим постам в этой ветке.
Разумеется, для того, чтобы ваш объект умел "правильно" сериализироваться, т.е., правильно сохранять свое состояние, необходимо самому об этом позаботиться. Предполагается, что вы уже это сделали, если же нет, то, чтобы долго не объяснять, ищи статью "Сериализация объектов в Делфи" или что-то в таком роде, в Инете имеется.
← →
w666w (2005-06-13 16:29) [13]> Просто Ждо
Большое спасибо, код рабочий. Единственное, что после сохранения объекта в строку он из этой же строки восстанавлмваться не хочет почему то... Наверное проблемы с сериализацией как уже было сказано...
> Stanislav
Метод, предложенный Просто Джо хорош, но в нем есть 1 минус. Для моей задачи главное - минимальный размер результирующей строки (для уменьшения времени на загрузку/сохранение). То есть визуальный смысл строки не имеет абсолютно никакого смысла. А в примере Просто Джо размер искуственно увеличен за счет читаемости. Пытаюсь реализовать приведенный Вами пример, никак не получается:
function SaveComponentToString(aComponent : TComponent) : string;
var fResult : string;
_M: TMemoryStream;
fStrings : TStrings;
begin
fResult := "";
_M := TMemoryStream.Create;
fStrings := TStrings.Create;
try
_M.WriteBuffer(aComponent, sizeof(aComponent));
_M.Position := 0;
fStrings.LoadFromStream(_M);
fResult := fStrings.Text;
ShowMessage(fStrings.Text);
finally
_M.Free;
fStrings.Free;
end;
Result := fResult;
end;
Убрал мемо, но с ним было та же ошибка:
на строке fStrings.LoadFromStream(_M); постоянно EAbstractError
Что не так?
← →
Erik1 © (2005-06-13 16:58) [14]А почему пример другой взял? В исходном примере ReadComponent и WriteComponent используется, их можно прямо в StringStream читать и писать.
← →
Stanislav © (2005-06-13 17:03) [15]w666w (13.06.05 16:29) [13]
TStringList попробуйте, там вобщем можно посмотреть как это реализованно и обойтись без него.
← →
w666w (2005-06-13 18:18) [16]Нашел именно то решение, которое искал:
function SaveComponentToString(aComponent : TComponent) : string;
var AStrStream: TStringStream;
begin
Result := "";
AStrStream := TStringStream.Create("");
try
AStrStream.WriteComponent(aComponent);
Result := AStrStream.DataString;
finally
AStrStream.Free;
end;
end;
function LoadComponentFromString(AComponent: TComponent; AString: string) : boolean;
var
AStrStream: TStringStream;
fResult : boolean;
begin
fResult := false;
AStrStream := TStringStream.Create(AString);
try
AStrStream.ReadComponent(AComponent);
fResult := true;
finally
AStrStream.Free;
end;
Result := fResult;
end;
Все оказалось довольно просто. Огромное спасибо всем кто помог. Удачи!
Страницы: 1 вся ветка
Текущий архив: 2005.07.11;
Скачать: CL | DM;
Память: 0.49 MB
Время: 0.041 c