?
Solved

Need  to write this data structure to a file..

Posted on 2001-09-14
7
Medium Priority
?
160 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
7 Comments
 
LVL 3

Accepted Solution

by:
cubud earned 150 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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…
Suggested Courses
Course of the Month15 days, 6 hours left to enroll

770 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