Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 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.039 c
7-89589
RAN
2003-07-16 05:32
2003.10.27
Отключение устройств


1-89288
LinOS
2003-10-17 05:57
2003.10.27
Указания компилятору что бы брал разные строки кода


3-89188
dez
2003-10-06 12:12
2003.10.27
MDAC


14-89470
Юлька
2003-10-07 11:25
2003.10.27
Ребята, не подскажите где можно в интернете найти


14-89505
Думкин
2003-10-09 04:50
2003.10.27
С днем рождения! 9 октября.