Solved

Need  to write this data structure to a file..

Posted on 2001-09-14
7
155 Views
Last Modified: 2010-04-06
OK, I need help desperately !!!

I have a (VERY VERY) complex data structure.

I need to be able to write this data stucture to a file, and I also need to read this structure from a file.

The data structure ("MACRO") is as follows.

(****************** BEGIN ********)
Type
  Rec = Record
     Name1, Name2: String;
     X,Y:Integer;
  end;

  LineRec = Record
     statement: Char;
     Action:Integer;
     ObjectCount:Integer;//Number of elements in the variable ObjectInfo array below.
     ObjectInfo : Array of Rec;
  End;

  Macro=Record   //Structure that needs to be written to a file.
    Name: String;
    LinesCount:Integer; //Number of elements in the variable Line array below.
    Line: array of LineRec;
  End;

(****************** END ********)

Ok, I need to have a file of "Macro" objects, so that I can write many "Macro" objects to the file, and then read the "Macro" objects(from the file) into an array of Macro Objects

Help please....

Im using Delphi 5 - if that helps in any way...

Thanx
0
Comment
Question by:CyberKnight
7 Comments
 
LVL 3

Accepted Solution

by:
cubud earned 50 total points
ID: 6483566
You are making a nightmare for yourself.

You should really use descendents of TPersistent (objects) and use collections for the arrays.

That way you can do

Writer := TWriter.Create(MyFileStream, 4096);
try
  Writer.WriteComponent(MyBaseComponent);
finally
  Writer.Free;
end;

You can probably guess TReader :)

Look at my 2 articles on component writing.
http://www.howtodothings.com/showarticle.asp?article=310
http://www.howtodothings.com/showarticle.asp?article=320

Part 1 is about the basics, part 2 is about Collections etc.

Pete
====
http://www.HowToDoThings.com (Programming articles)
http://www.StuckIndoors.com/delphi (Open source)
0
 
LVL 2

Expert Comment

by:bugroger
ID: 6483574
Hi,

i hope you can need it!

(****************** BEGIN ********)
Type
 TRec = Record
         Name1, Name2: String;
         X,Y:Integer;
        end;

 TLineRec = Record
             statement  : Char;
             Action     :Integer;
             ObjectCount:Integer; //Number of elements in the variable ObjectInfo array below.
             ObjectInfo : Array of TRec;
            End;

 TMacro = Record               //Structure that needs to be written to a file.
           Name      : String;
           LinesCount:Integer; //Number of elements in the variable Line array below.
           Line      : array of TLineRec;
          End;

 TMacroMain = array of TMacro;


Function Write_MacroStruct(MacroFileName : String; VAR M : TMacroMain) : Boolean;
VAR
 MacroFile : Cardinal; //File handle
 Written   : Cardinal; //for WriteFile()
 Main      : Integer;
 z1, z2    : Integer;
 b         : byte;

 Procedure WriteString(s : string);
 Begin
  WriteFile(MacroFile, Pchar(s)[0], Length(s) +1, Written, NIL);
 End;
 Procedure WriteInteger(i : integer);
 Begin
  WriteFile(MacroFile, i, 4, Written, NIL);
 End;

Begin
 Result := TRUE;

 //Create Macro File
 MacroFile := CreateFile(PChar(MacroFileName), GENERIC_WRITE, FILE_SHARE_WRITE,
                         NIL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
 IF MacroFile = INVALID_HANDLE_VALUE then
 Begin
  Result := FALSE;
  Exit;
 End;

 TRY
  b := 0;
  For Main := 0 to High(M) do
  Begin
   With M[Main] do
   Begin
    //TMacro
    WriteString(Name);
    WriteInteger(LinesCount);
    For z1 := 0 to LinesCount -1 do
    Begin
     //TLineRec
     WriteFile(MacroFile, Line[z1].statement, 1, Written, NIL);
     WriteInteger(Line[z1].Action);
     WriteInteger(Line[z1].ObjectCount);
     For z2 := 0 to Line[z1].ObjectCount-1 do
     Begin
      //TRec
      WriteString(Line[z1].ObjectInfo[z2].Name1);
      WriteString(Line[z1].ObjectInfo[z2].Name2);
      WriteInteger(Line[z1].ObjectInfo[z2].X);
      WriteInteger(Line[z1].ObjectInfo[z2].Y);
     End;
    End;
   End;
   IF Main = High(M) then b := 1;
   WriteFile(MacroFile, b, 1, Written, NIL);
  End;

 EXCEPT
  Result := FALSE;
 END;

 //Close Macro File
 CloseHandle(MacroFile);
End;


Function Read_MacroStruct(MacroFileName : String; VAR M : TMacroMain) : Boolean;
VAR
 MacroFile : Cardinal; //File handle
 Read      : Cardinal; //for ReadFile()
 Main      : Integer;
 z1, z2    : Integer;
 b         : byte;


 Function ReadString : String;
 VAR
  CharByte : Char;
 Begin
  Result := '';
  Repeat
   ReadFile(MacroFile, CharByte, 1, Read, NIL);
   IF (CharByte <> #0)and(Read <> 0) then Result := Result + CharByte
                                     else Exit;
  Until False;
 End;

 Function ReadInteger : Integer;
 Begin
  ReadFile(MacroFile, Result, 4, Read, NIL);
 End;

Begin
 Result := TRUE;

 //Open Macro File
 MacroFile := CreateFile(PChar(MacroFileName), GENERIC_READ, FILE_SHARE_READ,
                         NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
 IF MacroFile = INVALID_HANDLE_VALUE then
 Begin
  Result := FALSE;
  Exit;
 End;

 TRY
  Main := 0;
  Repeat
   SetLength(M, Main +1);
   With M[Main] do
   Begin
    //TMacro
    Name       := ReadString;
    LinesCount := ReadInteger;
    SetLength(Line, LinesCount);
    For z1 := 0 to LinesCount -1 do
    Begin
     //TLineRec
     ReadFile(MacroFile, Line[z1].statement, 1, Read, NIL);
     Line[z1].Action      := ReadInteger;
     Line[z1].ObjectCount := READInteger;
     SetLength(Line[z1].ObjectInfo, Line[z1].ObjectCount);
     For z2 := 0 to Line[z1].ObjectCount-1 do
     Begin
      //TRec

      Line[z1].ObjectInfo[z2].Name1 := ReadString;
      Line[z1].ObjectInfo[z2].Name2 := ReadString;
      Line[z1].ObjectInfo[z2].X     := ReadInteger;
      Line[z1].ObjectInfo[z2].Y     := ReadInteger;
     End;
    End;
   End;
   ReadFile(MacroFile, b, 1, Read, NIL);
   IF b <> 1 then Inc(Main);
  Until (b = 1);
 EXCEPT
  Result := FALSE;
 END;

 //Close Macro File
 CloseHandle(MacroFile);
End;


GL
 Bug
0
 
LVL 6

Expert Comment

by:edey
ID: 6485019
For something like this I would sugest XML - it is very good for storing heriecrical data, there a re existing parsers, and it's easy to troble shoot.  The only real disadvantage is that it's not always a very compact way of representing your data.

GL
Mike
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 3

Expert Comment

by:rondi
ID: 6486726
Nice code bugroger - does the trick.
However, it's not very extensible: one slight change to the
record structure and you've got a problem.

I'd go with cubud's suggestion. I use Delphi's in-built component streaming quite a lot. It's easy to add properties and stuff when you descend from TPersistent.
It's also more generic & flexible - if you need to add
or remove functionality later it'll be a piece of cake.

XML would do fine. But it's still not as elegant.
I use XML storage with VB only coz feeble VB doesn't support object streaming. Ideally, each object oughta know
what it needs to store and be responsible for it.
0
 

Author Comment

by:CyberKnight
ID: 6503036
Hi...
Bugroger code works well....

but like rondi said - Its not very flexible....if the structure needs changing - then the code has to be changed accordingly.

cubud approach *seems* to be more effecient.

But even though Ive read his articles, Im not able to write the code for the structure... Ive never used Tcollection, and never created my own descendents of TPersistent. Could someone please help with some code to show me how its done (in regards to my structure)..?

Thank you all...
0
 
LVL 3

Expert Comment

by:rondi
ID: 6503264
I'll try whip up something tonight...
0
 
LVL 3

Expert Comment

by:rondi
ID: 6503265
try
  WhipUpSomethingTonight;
except
  ApologizeTomorrow;
end;
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.
This is a video describing the growing solar energy use in Utah. This is a topic that greatly interests me and so I decided to produce a video about it.

919 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now