Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Можно ли в типиз. файле сохранить динамический


Автор: Sniper 28.10.2003, 22:50
Я вот пишу:
Код

 objects: array of TObjects;

var
 savesettings: File of TObjects;
 gsavesettings: TObjects;

// запись
assignfile(savesettings,'C:\config_cfg.cfg');
rewrite(savesettings);
write(savesettings,gsavesettings);
closefile(savesettings);
// чтение
assignfile(savesettings,'C:\config_cfg.cfg');
reset(savesettings);
read(savesettings,gsavesettings);
closefile(savesettings);

В файле пишутся только несколько пробелов! Как мне быть?

Автор: p0s0l 29.10.2003, 00:05
Расскажи поподробнее, какие объекты ты хочешь записать. Если это компоненты (наследники TComponent), то можно попробовать через потоки...

Автор: Sniper 29.10.2003, 00:16
поподробнее так поподробнее :-))

Я хочу записать:
Код

type
 Tobj0Vector = record
  x,y,z,w : single;
 end;
 Tobj1Vector = record
  x_dir,y_dir,z_dir : single;
 end;
 Tobj2Vector = record
  x,y,z, angle_x, angle_y, angle_z, scale_x, scale_y, scale_z : single;
  model : TModel;
  texture : GLuInt;
 end;

var
 objects0: array of Tobj0Vector;
 objects1: array of Tobj1Vector;
 objects2: array of Tobj2Vector;

Вот такие массивы! %-)

Автор: Vit 29.10.2003, 00:16
Запись типа объекта так как вы делаете приводит к записи в файл лишь 4х байтового значения указателя на объект.

Автор: p0s0l 29.10.2003, 00:20
Записать массивы из Tobj0Vector и Tobj1Vector - легко...
А насчет Tobj2Vector - в принципе это тоже решаемо, если раскажешь что такое TModel...

Автор: Sniper 29.10.2003, 00:20
p0s0l
А как? %-)

TModel = class
Meshes : TList; // Сетки
CurMesh : word; // Текущий кадр
TexVertices : PGLVertexArray; // Массив вершин текстуры
TexFaces : PGLFacesArray; // Массив граней текстуры
{animation speed}
TimeIsSet : boolean;
TimeEnd : dword;
{model info}
MeshCount, //meshes count
MeshVCount, //mesh vertices count
MeshFCount : word; //mesh faces count
isFaset, //1=faset normals was included
isSmooth : byte; //1=smooth normals was included
TexVCount, //tex vertices count
TexFCount : word; //tex faces count
IsOwnTexture : byte; //1=texture file was included
{}
OwnTexture : gluint; //use if texture file included

Автор: p0s0l 29.10.2003, 00:26
TList, TGLVertexArray, TGLFacesArray - тоже их распиши...

Автор: Sniper 29.10.2003, 00:29
PGLVertex = ^TGLVertex;
TGLVertex =
record
x,y,z : glfloat;
end;

PGLVector = ^TGLVector;
TGLVector = array[0..2] of glfloat;//тип GLFloat = single

PGLFace = ^TGLFace;
TGLFace = array[0..2] of word;

PGLVertexArray = ^TGLVertexArray;
TGLVertexArray = array[Word] of TGLVertex;

PGLFacesArray = ^TGLFacesArray;
TGLFacesArray = array[word] of TGLFace;

Автор: p0s0l 29.10.2003, 00:53
Это писалось навскидку, так что должны быть глюки...
Запись:
Код
var
 s : TFileStream;
 i : integer;
begin
 s := TFileStream.Create('c:\config_cgf.cfg', fmCreate);
// Запись objects0
 i := Length(objects0);
 s.Write(i, SizeOf(i));
 s.Write(objects0[0], SizeOf(Tobj0Vector)*Length(objects0));
// Запись objects1
 i := Length(objects1);
 s.Write(i, SizeOf(i));
 s.Write(objects1[0], SizeOf(Tobj1Vector)*Length(objects1));
// Запись objects2
 i := Length(objects2);
 s.Write(i, SizeOf(i));
 s.Write(objects2[0], SizeOf(Tobj2Vector)*Length(objects2));
// Запись моделей, на которые идут ссылки из массива objects2
 for i := 0 to Length(objects2)-1 do objects2[i].Model.SaveToStream(s);
 s.Free;
end;

Чтение:
Код
var
 s : TFileStream;
 i : integer;
begin
 s := TFileStream.Create('c:\config_cgf.cfg', fmOpenRead);
// Чтение objects0
 s.Read(i, SizeOf(i));
 SetLength(objects0, i);
 s.Read(objects0[0], SizeOf(Tobj0Vector)*Length(objects0));
// Чтение objects1
 s.Read(i, SizeOf(i));
 SetLength(objects1, i);
 s.Write(objects1[0], SizeOf(Tobj1Vector)*Length(objects1));
// Чтение objects2
 s.Read(i, SizeOf(i));
 SetLength(objects2, i);
 s.Write(objects2[0], SizeOf(Tobj2Vector)*Length(objects2));
// Чтение моделей, на которые идут ссылки из массива objects2
 for i := 0 to Length(objects2)-1 do
 begin
   objects2[i].Model := TModel.Create(...тут ты сам должен знать что писать...);
   objects2[i].Model.LoadFromStream(s);
 end;
 s.Free;
end;


Только в классе TModel придется добавить два метода в секции Public:
Для записи:
Код
procedure TModel.SaveToStream(s : TFileStream);
begin
 s.Write(CurMesh, SizeOf(CurMesh));
 s.Write(TimeIsSet, SizeOf(TimeIsSet));
 ... // и т.д. записываешь все данные, кроме массивов
 s.Write(OwnTexture, SizeOf(OwnTexture));
// Запись массивов
 s.Write(TexVertices^, SizeOf(TGLVertex)*TexVCount);
 s.Write(TexFaces^, SizeOf(TGLFace)*TexFCount);
end;

Для чтения:
Код
procedure TModel.LoadFromStream(s : TFileStream);
begin
 s.Read(CurMesh, SizeOf(CurMesh));
 s.Read(TimeIsSet, SizeOf(TimeIsSet));
 ... // и т.д. записываешь все данные, кроме массивов
 s.Read(OwnTexture, SizeOf(OwnTexture));
// Выделение памяти под массивы
 GetMem(TexVertices, SizeOf(TGLVertex)*TexVCount);
 GetMem(TexFaces, SizeOf(TGLFace)*TexFCount);
// Чтение массивов
 s.Read(TexVertices^, SizeOf(TGLVertex)*TexVCount);
 s.Read(TexFaces^, SizeOf(TGLFace)*TexFCount);
end;

Для Mesh : TList - сам сделаешь, т.к. так и не написал, что это такое...

Автор: Sniper 29.10.2003, 22:00
p0s0l
TList - это стандартный класс Delphi! %-) Находится в Classes!

Автор: p0s0l 29.10.2003, 23:53
Цитата
p0s0l
TList - это стандартный класс Delphi! %-) Находится в Classes!

sad.gif
Ты видимо не понял суть затруднений сохранения данных в файл... А эта трудность заключается в сохранении динамических данных.
Первый раз с этим встречаешься в objects2. TModel - это класс, а значит поле model - это лишь указатель на объект. Запись этого указателя в файл ничего не даст, т.к. сам объект в файл не запишется, а запишется только лишь его адрес... Поэтому были сделаны два метода для записи/чтения модели.
Второй раз это были TexVertices и TexFaces из класса TModel - они тоже лишь указатели на массивы...
И третий - TList, который ты никак не хочешь расписать, что же в нем всё-таки хранится... Ведь TList - это массив указателей. И запись этих указателей опять-таки бессмыслена. Надо знать, на что ссылаются эти указатели. А из тебя как из партизана надо вытягивать все эти данные...
Тебе надо было идти в разведчики...

Автор: Sniper 30.10.2003, 00:26
Вырезка из модуля Classes.pas

Код

{ Maximum TList size }
const
 MaxListSize = Maxint div 16;
{ TList class }

 PPointerList = ^TPointerList;
 TPointerList = array[0..MaxListSize - 1] of Pointer;
 TListSortCompare = function (Item1, Item2: Pointer): Integer;
 TListNotification = (lnAdded, lnExtracted, lnDeleted);

 // these operators are used in Assign and go beyond simply copying
 //   laCopy = dest becomes a copy of the source
 //   laAnd  = intersection of the two lists
 //   laOr   = union of the two lists
 //   laXor  = only those not in both lists
 // the last two operators can actually be thought of as binary operators but
 // their implementation has been optimized over their binary equivalent.
 //   laSrcUnique  = only those unique to source (same as laAnd followed by laXor)
 //   laDestUnique = only those unique to dest   (same as laOr followed by laXor)
 TListAssignOp = (laCopy, laAnd, laOr, laXor, laSrcUnique, laDestUnique);

 TList = class(TObject)
 private
   FList: PPointerList;
   FCount: Integer;
   FCapacity: Integer;
 protected
   function Get(Index: Integer): Pointer;
   procedure Grow; virtual;
   procedure Put(Index: Integer; Item: Pointer);
   procedure Notify(Ptr: Pointer; Action: TListNotification); virtual;
   procedure SetCapacity(NewCapacity: Integer);
   procedure SetCount(NewCount: Integer);
 public
   destructor Destroy; override;
   function Add(Item: Pointer): Integer;
   procedure Clear; virtual;
   procedure Delete(Index: Integer);
   class procedure Error(const Msg: string; Data: Integer); overload; virtual;
   class procedure Error(Msg: PResStringRec; Data: Integer); overload;
   procedure Exchange(Index1, Index2: Integer);
   function Expand: TList;
   function Extract(Item: Pointer): Pointer;
   function First: Pointer;
   function IndexOf(Item: Pointer): Integer;
   procedure Insert(Index: Integer; Item: Pointer);
   function Last: Pointer;
   procedure Move(CurIndex, NewIndex: Integer);
   function Remove(Item: Pointer): Integer;
   procedure Pack;
   procedure Sort(Compare: TListSortCompare);
   procedure Assign(ListA: TList; AOperator: TListAssignOp = laCopy; ListB: TList = nil);
   property Capacity: Integer read FCapacity write SetCapacity;
   property Count: Integer read FCount write SetCount;
   property Items[Index: Integer]: Pointer read Get write Put; default;
   property List: PPointerList read FList;
 end;

Автор: Vit 30.10.2003, 00:31
2 Sniper - мы вообще-то знаем модуль classes.pas, ровно как и классы в нём прописанные, приводить его не обязательно, а если привёл, так поясни - зачем? Что в этом коде тебя смущает?

Автор: Sniper 30.10.2003, 00:33
Vit
Это надо p0s0l спросить! %-) что в этом коде его смущает!
Он просил: расписать TList - я выполнил его просьбу! %-)

Автор: p0s0l 30.10.2003, 10:12
Цитата
TList - это массив указателей

Цитата
Надо знать, на что ссылаются эти указатели

Или ты его используешь для хранения не указателей, а чего-то другого ? Вообще, ты делал ту прогу, или откуда-то взял ?

Автор: Dmitry V.Abramov 30.10.2003, 15:45
p0s0l Ты забыл еще спросить, - а надо ли ему это вообще... Судя по публикациям classes.pas и усмешкам - не очень то и надо.

Автор: p0s0l 30.10.2003, 16:52
Просто Sniper никак не хочет понять, что от него хотят...
Это моя последняя попытка: "Снайпер, скажите нам, НА ЧТО же всё-таки ССЫЛАЮТСЯ те самые указатели из TLIST ? Т.е. распишите те типы структур/объектов на которые ссылается этот TList."

Автор: Vit 30.10.2003, 18:25
Цитата(Sniper @ 29.10.2003, 15:33)
Vit
Это надо p0s0l спросить! %-) что в этом коде его смущает!
Он просил: расписать TList - я выполнил его просьбу! %-)

Похоже вы не поняли, что он от Вас хочет. Для программиста на Дельфи модуль classes.pas и классы в нём прописанные, всё равно что 4 арифметических действия для математика - зная уровень p0s0l я не сомневаюсь, что он прекрасно осведомлён и о модуле classes.pas и о классе TList, поэтому попытайтесь понять те вопросы, которые Вам задают и ответить на них, проблема в Вашем понимании задачи, а не понимании нами этого модуля и класса TList. (без обид, Вам действительно хотят помочь, но к сожалению мы должны понять ЧТО именно надо).

Автор: Sniper 30.10.2003, 20:39
Я понимаю и ценю вашу помощь!

Но я, как сказал Vit, не понимаю что вам дать чтобы вы мне помоги! :-(((((
p0s0l поверь я хочу тебе сказать на что они указываю.... знать бы только как!!
(у меня проект стоит! из-за моей тупизны :-(

публикую все типы которые содержатся в модуле model.pas
Код

Type
   PGLVertex = ^TGLVertex;
   TGLVertex =
   record
     x,y,z : glfloat;
   end;

   PGLVector = ^TGLVector;
   TGLVector = array[0..2] of glfloat;

   PGLFace   = ^TGLFace;
   TGLFace   = array[0..2] of word;

   PGLVertexArray = ^TGLVertexArray;
   TGLVertexArray = array[Word] of TGLVertex;

   PGLFacesArray  = ^TGLFacesArray;
   TGLFacesArray  = array[word] of TGLFace;

   TGMD = class;

   TGMDMesh =
   class
     Vertices,                       // Массив вершин
     FasetNormals,                   // Массив фасетных нормалей
     SmoothNormals : PGLVertexArray; // Массив сглаживающих нормалей
     Faces         : PGLFacesArray;  // Массив граней
     Parent        : TGMD;
   private
     procedure Draw;
   public
     destructor Destroy; override;
   end;

   TGMD = class
     Meshes         : TList;          // Сетки
     CurMesh        : word;           // Текущий кадр
     TexVertices    : PGLVertexArray; // Массив вершин текстуры
     TexFaces       : PGLFacesArray;  // Массив граней текстуры
     {animation speed}
     TimeIsSet      : boolean;
     TimeEnd        : dword;
     {model info}
     MeshCount,                  //meshes count
     MeshVCount,                 //mesh vertices count
     MeshFCount     : word;      //mesh faces count
     isFaset,                    //1=faset normals was included
     isSmooth       : byte;      //1=smooth normals was included
     TexVCount,                  //tex vertices count
     TexFCount      : word;      //tex faces count
     IsOwnTexture   : byte;      //1=texture file was included
     {}
     OwnTexture     : gluint;    //use if texture file included
   public
     procedure SaveToStream1(s : TFileStream);
     procedure LoadFromStream1(s : TFileStream);
     function    LoadFromFile(FileName,ModelName:String):boolean;
     procedure   Draw(StartMesh,EndMesh:word; mps:byte);
     constructor Create;
     destructor  Destroy; override;
   end;


Там дальше по тексту пишу:
Meshes := TList.Create;

Я кажись начинаю понимать, что вам нужно! :-)
вот например:
TexFaces : PGLFacesArray; но PGLFacesArray указывает на ^TGLVertexArray который в свою очередь указывает на array[Word] of TGLVertex; а тот на

TGLVertex = record
x,y,z : glfloat;
end;
так вам нужно вот такое же как эта цепочка, только про TList? Я правильно понял? Если да то для TList ТАКОЙ ЦЕПОЧКИ НЕТ! :-( Он просто берётся из этого ...... classes.pas Тьфу!

Автор: <Spawn> 30.10.2003, 23:04
Sniper Смотри, указатели могут ссылаться на данные разных типов. К примеру, в TList могут быть указатели на тип integer( PInteger), а могут и на целые структуры:

Код
PSomeRec = ^TSomeRec;
TSomeRec = record
  Field1:Byte;
  Field2:Word;
  Field3:string[10];
 end;


Так вот у тебя пытаются выяснить на какой тип данных указывают указатели в TList?? Или они у тебя вообще не типизированные(Pointer)?

К примеру, если бы в TList "сидели" PInteger, то запись могла бы быть примерно такой

Код
for i:=0 to List.Count-1 do
 Запись значения PInteger(List.Items[i])^

Автор: Sniper 30.10.2003, 23:20
<Spawn> понятно! wink.gif Ну что я могу ответить.... нету у меня ничего похожего на них только есть такие строчки:

Meshes.Add(ogmd_NextMesh);
TGMDMesh(Meshes.Items[CurMesh]).Draw;

for i:=0 to Meshes.Count-1 do TGMDMesh(Meshes.Items[i]).Destroy;

Больше в модуле нигде не встречается Meshes
а TList описан в classes.pas.... а как уж в этом модуле идут ссылки всем известно!

Автор: p0s0l 30.10.2003, 23:24
Посмотри какой тип у переменной ogmd_NextMesh - судя по смыслу должно быть TGMDMesh...
Если это так, то тут возникают трудности:
у TGMDMesh есть ссылки на массивы Vertices, FasetNormals, SmoothNormals, Faces, но нет ничего, что могло бы помочь узнать размеры этих массивов - следовательно по той приведенной части кода запись/чтение сделать скорее всего невозможно.
Было бы легче, если бы ты показал метод LoadFromFile, наверняка там эти массивы заполняются...

Автор: <Spawn> 30.10.2003, 23:34
p0s0l Хм, я что то не понимаю или ты не обратил внимания, но TGLVertex имеет размер 65536 (SizeOf(Word)) структур, содержащих 3 значения типа Float(в OpenGL почти ко всем типам приделаны приставки gl).

Автор: p0s0l 30.10.2003, 23:44
Sniper, не надо, ничего не смотри, я протормозил - в TList'е однозначно хранятся переменные типа TGMDMesh (либо его наследники, но это маловероятно, тем более ты привел все типы из того модуля)...

<Spawn>, так вообще-то и делают... Можно было описать TGLVertexArray как array [0..0] of TGLVertex - ничего бы не изменилось. Вернее в последнем варианте с включенной опцией Range Checking вывалилась бы ошибка при обращении, например, к элементу [1]. Но она обычно выключена (по умолчанию).
Просто реальный размер массива задаётся при выделении памяти:
var p : PGLVertexArray;
GetMem (p, 1024*SizeOf(TGLVertex)); // это массив из 1024 элементов

Автор: Unregistered 1.11.2003, 18:47
p0s0l
я сделал так s.Write(Meshes, SizeOf(TList));
и 60kb в файле файле конфигурации прибавилось, а было 40 байт! %-)
Я чувстую что я правильно сделал!?

Автор: Sniper 1.11.2003, 18:50
p0s0l
я сделал так s.Write(Meshes, SizeOf(TList));
и 60kb в файле файле конфигурации прибавилось, а было 40 байт! %-)
Я чувстую что я правильно сделал!?

Автор: Dmitry V.Abramov 1.11.2003, 22:08
Sniper На этот раз предчувствия тебя обманывают...

SizeOf(TList))=SizeOf(TForm)=SizeOf(T_Что_угодно_порожденное_от_TObject)=4. Везде. Даже если Папа Римский наберет сейчас дрожащими руками в католическом Delphi "writeln(SizeOf(TList))", то сниспослано ему в ответ будет число 4. И это правильно. И это можно не знать, а нужно просто помнить. Как 2х2.

А передачу Meshes в качестве параметра на запись - обязательно надо предложить Borland'у. А то понагородили тут какие-то RTTI, {M+}, TPersistent, TWriter, TReader... Попутно выдумали "проблему сохранения и восстановления классов" на нашу голову... А ее, оказывается, нет - сохраним 4 байта адреса из Heap - и хватит. Но! Главное - не выдать врагу этот метод! Пусть это будет нашим секретом.

Резюме: ответ отрицательный.

Автор: Sniper 1.11.2003, 22:46
Dmitry V.Abramov Но у меня файл весит не 4 байта, а 60KB!!!!
Что же он тогда сохраняетconfused.gif?

Автор: p0s0l 2.11.2003, 11:31
Sniper, дак ведь ты не один меш сохраняешь в файл ? Из-за этого и получается такой размер...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)