Solved

Need  to write this data structure to a file..

Posted on 2001-09-14
7
156 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
The Eight Noble Truths of Backup and Recovery

How can IT departments tackle the challenges of a Big Data world? This white paper provides a roadmap to success and helps companies ensure that all their data is safe and secure, no matter if it resides on-premise with physical or virtual machines or in the cloud.

 
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

DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Find and Replace Stream with 0s 8 62
Dynamically Created Query 3 55
Breakpoint doesn't stop in my variable 3 28
Delphi problems to abort a printjob 9 20
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
This Micro Tutorial will teach you how to censor certain areas of your screen. The example in this video will show a little boy's face being blurred. This will be demonstrated using Adobe Premiere Pro CS6.
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.

809 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