Текущий архив: 2003.10.27;
Скачать: CL | DM;
Вниз
Сохранение TList в файл Найти похожие ветки
← →
$Hic0 © (2003-10-16 12:49) [0]Добрый день!
У меня имеется объект List типа TList поле items которого заполненно объектами типа TData (определнный мной тип), думаю это не важно, так вот, требуется сохранить это хозяйство в файл.
Пишу:
Begin
Stream:=TFileStream.Create(SaveDialog1.FileName,fmCreate);
Stream.Write(List,List.Count);
Stream.Free;
End;
В файл что-то сохраняется, но естественно не то, посколько Count не есть число байтов в которых умещаются все итемы и объекты TData находящиеся в них... Вопросов несколько:
1. Правильно-ли я делаю что использую для этого потоки, может я изобретаю велосипед, и есть другая возможность, хотя я искал и не нашел у TList метода записи в файл
2. Как мне определить количество байт необходимых для записи, может сделать так: List.Count*List.Capacity ? (пробовал все равно не то).
3. Может я все делаю правильно? Заключение о неверности сохранения сделано из того что после загрузки из сохраненного файла объект List пустой.
4. В С# я бы сделал это через бинарную сериализацию, нет-ли аналогичной возможности в дельфи?
Да вроде и все :) Извините за наглость за объединение четырех вопросов в один, заранее спасибо за ответ!
Кто знает как можно решить эту проблему?
← →
Reindeer Moss Eater © (2003-10-16 12:50) [1]TList содержит 4 байтовые указатели и больше ничего.
Их ты успешно и сохраняешь.
← →
Skier © (2003-10-16 12:50) [2]
> которого заполненно объектами типа TData (определнный мной
> тип), думаю это не важно
Это очень важно !
← →
$Hic0 © (2003-10-16 12:53) [3]ок :)
TData=class(TPersistent)
public
State,Adress :integer;
Owner :TNode;
Mera :single;
Virt :boolean;
procedure Assign(source :TPersistent);override;
procedure CLear;
end; { TData }
Вот она моя TData :)
← →
Skier © (2003-10-16 12:55) [4]>$Hic0 © (16.10.03 12:53) [3]
и что из TData ты желаешь сохранять ?
← →
$Hic0 © (2003-10-16 12:56) [5]Блин а вот и TNode и TEventNode :)
TEventNode=procedure(Node :TComponent) of object;
TNode=class(TComponent)
private
FOnFree :TEventNode;
function GetItem(index :integer) :TNode;
public
Data :pointer;
function Parent :TNode;
function LeveL :integer;
function HasChildren :boolean;
function FirstChild:TNode ;
function LastChild :TNode ;
function Count :integer;
property Item[index :integer] :TNode read GetItem ;
property OnFree :TEventNode read FOnFree write FOnFree;
constructor Create(AOwner :TComponent);override;
procedure Free;
end;{ TNode }
← →
$Hic0 © (2003-10-16 12:58) [6]желаю сохранять все :) Мне нужно что-бы объект List восстанавливался таким какой он есть, все поля жизненно необходимы, потому что на этой структуре построенна вся моя программа, по ней производится поиск, выборка, и т.д.
← →
Reindeer Moss Eater © (2003-10-16 13:00) [7]Мне нужно что-бы объект List восстанавливался таким какой он есть
Он у тебя и восстанавливается каким был.
Просто в нем ничего кроме указателей по определению нет.
Надо сохранять объекты на которые эти указатели указывают, а не сам TList
← →
$Hic0 © (2003-10-16 13:04) [8]Да, теперь понятно, я просто думал что Stream.Write пробежится по указателям, зацепит все и сохранет, выходит я ошибался...
← →
Skier © (2003-10-16 13:09) [9]
> Stream.Write пробежится по указателям, зацепит все и сохранет
А зачем тогда программист вообще нужен ?
"Скрипач не нужен !" (с) Кин-Дза-Дза
← →
Chieftain (2003-10-16 13:51) [10]> TList содержит 4 байтовые указатели и больше ничего.
Даже хуже... List это всего лишь указатель на объект TList :)))
Могу предложить два метода.
1. Перебираешь
for i := 0 to List.Count - 1 do begin
(List.Item as TData).SaveToStream(...)
end;
это геморно, но работает.
2. TPersistent умеет себя сохранять в потоки, кажется. Значит именно от него надо наследовать. И вообще статья была вроде на этом сайте, название типа "Как создать собственную базу данных" или чего-то такое.
← →
Плохиш_ (2003-10-16 14:10) [11]>$Hic0 © (16.10.03 13:04) [8]
Т.е. я так понимаю в c# есть такая функция?
← →
Amoeba (2003-10-16 15:40) [12]Могу предложить следующее эффективное решение:
- класс TData делаешь потомком TCollectionItem, а не TObject, добавляешь нужные поля и перекрываешь св-во Assign;
- вместо TList использовать потомка TCollection с перекрытыми методами Create, Add, GetItem, SetItem и свойством Items;
TMyCollection.Create;
begin
inherited Create(TData);
end;
TMyCollection.Add: TData;
begin
Result := inherited Add as TData;
end;
TMyCollection.GetItem(Idex: Integer): TData;
begin
Result := inherited GetItem(Index) as TData;
end;
TMyCollection.SetItem(Idex: Integer; value: TData);
begin
Result := inherited SetItem(Index, Value);
end;
- И теперь объявляешь класс
TMyData = class(TComponent)
private
FItems: TMyCollection;public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Items: TMyCollection read FItems write FItems;
end;
Что следует написать в конструкторе и деструкторе - расписывать не буду - и ежу понятно - создается/уничтожается коллекция FItems.
Экземпляр этого компонета достаточно создавать в RunTime.
И теперь для загрузки из потока делаем так:
Stream.ReadComponent(TMyData);
Естественно, экземпляр TMyData должен уже существовать
а для записи:
Stream.WriteRead(TMyData);
----
По-моему все довольно просто и эффективно!
← →
Amoeba (2003-10-16 15:47) [13]Sorry, должно быть:
Stream.ReadComponent(MyData);
Stream.WriteComponent(MyData);
Страницы: 1 вся ветка
Текущий архив: 2003.10.27;
Скачать: CL | DM;
Память: 0.5 MB
Время: 0.035 c