Solved

Need  to write this data structure to a file..

Posted on 2001-09-14
7
153 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
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
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

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

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 I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

744 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

12 Experts available now in Live!

Get 1:1 Help Now