Save class to file

Hi all,

I've a short question but first i'll explain my problem. I've a few classes who are 'linked' to each other. Now i want to store these classes in one single (binairy)file. Is that possible? Is there maybe a component?

I know that's possible with records (File Of Record).

Please help me!

Greetz,

Sander
KiwiFreaKAsked:
Who is Participating?
 
TheRealLokiSenior DeveloperCommented:
here's a complete example I wrote for you on how to load and save your owncustom defined classes to a file

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, contnrs; // for TObjectList - which automatically frees class objects in its list when you delete them - Loki

type TMyClass = class
    public
        name: string;
        age: integer;
        address: string;
        procedure SaveToStream(Stream: TStream);
        procedure LoadFromStream(Stream: TStream);
        constructor Create;
    end;

type
  TForm1 = class(TForm)
    bLoad: TButton;
    bSave: TButton;
    OpenDialog1: TOpenDialog;
    eName: TEdit;
    eAddress: TEdit;
    eAge: TEdit;
    bAddToMyList: TButton;
    Memo1: TMemo;
    bShowList: TButton;
    SaveDialog1: TSaveDialog;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure bLoadClick(Sender: TObject);
    procedure bSaveClick(Sender: TObject);
    procedure bAddToMyListClick(Sender: TObject);
    procedure bShowListClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    MyList: TObjectList;
    procedure LoadMyClassesFromFile;
    procedure SaveMyClassesToFile;
  end;

var
  Form1: TForm1;

IMPLEMENTATION

{$R *.DFM}

{ TMyClass }

constructor TMyClass.Create;
    begin
        inherited create;
        Name := '';
        Age := 0;
        Address := ''; //these are already blank, but i'm just showing where to put defaults
    end;

procedure TMyClass.LoadFromStream(Stream: TStream);
    var
        len: integer;
    begin
        Stream.Read(len, sizeof(len)); // get length of name
        Setlength(self.Name, len); // we need to make the string the right size to hold the data
        Stream.Read(self.Name[1], len); // read the name
        Stream.Read(self.Age, sizeof(self.Age)); // get age
        Stream.Read(len, sizeof(len)); // get length of address
        Setlength(self.Address, len); // we need to make the string the right size to hold the data
        Stream.Read(self.Address[1], len); // read the address
    end;

procedure TMyClass.SaveToStream(Stream: TStream);
    var
        len: integer;
    begin
        len := length(self.Name); // get the length of the name
        Stream.Write(len, sizeof(len)); // write length of name
        Stream.Write(self.Name[1], len); // write the name
        Stream.Write(self.Age, sizeof(self.Age)); // get age
        len := length(self.Address); // get the length of the address
        Stream.Write(len, sizeof(len)); // write length of address
        Stream.Write(self.Address[1], len); // write the address
    end;

procedure TForm1.FormCreate(Sender: TObject);
    begin
        MyList := TObjectList.Create;
    end;

procedure TForm1.FormDestroy(Sender: TObject);
    begin
        MyList.Clear;
        MyList.Free;
    end;

procedure TForm1.LoadMyClassesFromFile;
    var
        fs: TStream;
        total: integer;
        i: integer;
        newitem: TMyClass;
    begin
        MyList.Clear;
        if OpenDialog1.Execute then
        begin
            fs := TFileStream.Create(OpenDialog1.Filename, fmOpenRead);
            try
                fs.Read(total, sizeof(total)); // how many objects are in the file
                for i := 1 to total do
                begin
                    newitem := TMyClass.Create;
                    newitem.LoadFromStream(fs); // have each item load itself
                    MyList.Add(newitem); // add it to our list
                end;
            finally
                fs.free;
            end;
        end;
    end;

procedure TForm1.SaveMyClassesToFile;
    var
        fs: TStream;
        total: integer;
        i: integer;
        newitem: TMyClass;
    begin
        if SaveDialog1.Execute then
        begin
            fs := TFileStream.Create(SaveDialog1.Filename, fmCreate);
            try
                total := MyList.Count;
                fs.Write(total, sizeof(total)); // how many objects to save to file
                for i := 0 to pred(total) do
                  TMyClass(MyList[i]).SaveToStream(fs); // have each item save itself
            finally
                fs.free;
            end;
        end;
    end;

procedure TForm1.bLoadClick(Sender: TObject);
    begin
        LoadMyClassesFromFile;
    end;

procedure TForm1.bSaveClick(Sender: TObject);
    begin
        SaveMyClassesToFile;
    end;


procedure TForm1.bAddToMyListClick(Sender: TObject);
    var
        newitem: TMyClass;
    begin
        newItem := TMyClass.Create;
        newitem.Name := eName.Text;
        newitem.Age := StrToIntDef(eAge.Text, 0);
        newitem.Address := eAddress.Text;
        MyList.Add(newitem);
    end;

procedure TForm1.bShowListClick(Sender: TObject);
    var
        i: integer;
    begin
        memo1.lines.clear;
        for i := 0 to pred(MyList.Count) do
          memo1.lines.add(
        TMyClass(MyList[i]).name + ' : ' +
        IntToStr(TMyClass(MyList[i]).age) + ' : ' +
        TMyClass(MyList[i]).address);
       
    end;

end.




**************** FORM FOLLOWS *****************

object Form1: TForm1
  Left = 274
  Top = 213
  Width = 869
  Height = 623
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object bLoad: TButton
    Left = 96
    Top = 40
    Width = 75
    Height = 25
    Caption = 'bLoad'
    TabOrder = 0
    OnClick = bLoadClick
  end
  object bSave: TButton
    Left = 96
    Top = 80
    Width = 75
    Height = 25
    Caption = 'bSave'
    TabOrder = 1
    OnClick = bSaveClick
  end
  object eName: TEdit
    Left = 312
    Top = 48
    Width = 121
    Height = 21
    TabOrder = 2
    Text = 'eName'
  end
  object eAddress: TEdit
    Left = 312
    Top = 96
    Width = 121
    Height = 21
    TabOrder = 4
    Text = 'eAddress'
  end
  object eAge: TEdit
    Left = 312
    Top = 72
    Width = 121
    Height = 21
    TabOrder = 3
    Text = 'eAge'
  end
  object bAddToMyList: TButton
    Left = 448
    Top = 48
    Width = 89
    Height = 25
    Caption = 'bAddToMyList'
    TabOrder = 5
    OnClick = bAddToMyListClick
  end
  object Memo1: TMemo
    Left = 96
    Top = 120
    Width = 257
    Height = 153
    Lines.Strings = (
      'Memo1')
    TabOrder = 6
  end
  object bShowList: TButton
    Left = 448
    Top = 88
    Width = 89
    Height = 25
    Caption = 'bShowList'
    TabOrder = 7
    OnClick = bShowListClick
  end
  object OpenDialog1: TOpenDialog
    Left = 192
    Top = 72
  end
  object SaveDialog1: TSaveDialog
    Left = 232
    Top = 72
  end
end
0
 
paulb1989Commented:
You can save classes using TWriter and read them using TReader. It is easiest if you use classes derived from TComponent so you can use the WriteComponent method.
0
 
KiwiFreaKAuthor Commented:
Thanks for you answer and sorry for my late reply but; How can i save these classes in one file? Is that possible?


TAgeClass = class
              age : Integer;
              dateofbirth : string;
              cityofbirth : string[30];
              constructor Create;
            end;
TMyClass = class
    public
        name: string;
        age : TAgeClass;
        address: string;
        procedure SaveToStream(Stream: TStream);
        procedure LoadFromStream(Stream: TStream);
        constructor Create;
    end;

0
 
TheRealLokiSenior DeveloperCommented:
Do you want 1 TMyClass in a file? or many TMYClass'es in the file?
0
 
TheRealLokiSenior DeveloperCommented:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, contnrs; // for TObjectList - which automatically frees class objects in its list when you delete them - Loki

type TAgeClass = class
        age : Integer;
        dateofbirth : string;
        cityofbirth : string[30];
        constructor Create;
    end;

type TMyClass = class
    public
        name: string;
        age: TAgeClass;
        address: string;
        procedure SaveToStream(Stream: TStream);
        procedure LoadFromStream(Stream: TStream);
        constructor Create;
        destructor Destroy; override;
    end;

type
  TForm1 = class(TForm)
    bLoad: TButton;
    bSave: TButton;
    OpenDialog1: TOpenDialog;
    eName: TEdit;
    eAddress: TEdit;
    eAge: TEdit;
    bAddToMyList: TButton;
    Memo1: TMemo;
    bShowList: TButton;
    SaveDialog1: TSaveDialog;
    eDateOfBirth: TEdit;
    eCityOfBirth: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure bLoadClick(Sender: TObject);
    procedure bSaveClick(Sender: TObject);
    procedure bAddToMyListClick(Sender: TObject);
    procedure bShowListClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    MyList: TObjectList;
    procedure LoadMyClassesFromFile;
    procedure SaveMyClassesToFile;
  end;

var
  Form1: TForm1;

IMPLEMENTATION

{$R *.DFM}

{ TMyClass }

constructor TMyClass.Create;
    begin
        inherited create;
        Name := '';
        age := TAgeClass.Create;
        Address := ''; //these are already blank, but i'm just showing where to put defaults
    end;

destructor TMyClass.Destroy;
    begin
        Age.Free;
        inherited Destroy;
    end;

procedure TMyClass.LoadFromStream(Stream: TStream);
    var
        len: integer;
    begin
        Stream.Read(len, sizeof(len)); // get length of name
        Setlength(self.Name, len); // we need to make the string the right size to hold the data
        Stream.Read(self.Name[1], len); // read the name
// read age
        Stream.Read(self.Age.Age, sizeof(self.Age.Age)); // get age
        Stream.Read(len, sizeof(len)); // get length of address
        Setlength(self.Age.dateofbirth, len); // we need to make the string the right size to hold the data
        Stream.Read(self.Age.dateofbirth[1], len); // read the address
        Stream.Read(len, sizeof(len)); // get length of address
        Setlength(self.Age.cityofbirth, len); // we need to make the string the right size to hold the data
        Stream.Read(self.Age.cityofbirth[1], len); // read the address

        Stream.Read(len, sizeof(len)); // get length of address
        Setlength(self.Address, len); // we need to make the string the right size to hold the data
        Stream.Read(self.Address[1], len); // read the address
    end;

procedure TMyClass.SaveToStream(Stream: TStream);
    var
        len: integer;
    begin
        len := length(self.Name); // get the length of the name
        Stream.Write(len, sizeof(len)); // write length of name
        Stream.Write(self.Name[1], len); // write the name
// write age
        Stream.Write(self.Age.Age, sizeof(self.Age.Age)); // write age
        len := length(self.Age.dateofbirth); // get the date of birth
        Stream.Write(len, sizeof(len)); // write the date of birth
        Stream.Write(self.Age.dateofbirth[1], len); // write the date of birth
        len := length(self.age.cityofbirth); // get the length of city of birth
        Stream.Write(len, sizeof(len)); // write length of city of birth
        Stream.Write(self.age.cityofbirth[1], len); // write the city of birth

        len := length(self.Address); // get the length of the address
        Stream.Write(len, sizeof(len)); // write length of address
        Stream.Write(self.Address[1], len); // write the address
    end;

procedure TForm1.FormCreate(Sender: TObject);
    begin
        MyList := TObjectList.Create;
    end;

procedure TForm1.FormDestroy(Sender: TObject);
    begin
        MyList.Clear;
        MyList.Free;
    end;

procedure TForm1.LoadMyClassesFromFile;
    var
        fs: TStream;
        total: integer;
        i: integer;
        newitem: TMyClass;
    begin
        MyList.Clear;
        if OpenDialog1.Execute then
        begin
            fs := TFileStream.Create(OpenDialog1.Filename, fmOpenRead);
            try
                fs.Read(total, sizeof(total)); // how many objects are in the file
                for i := 1 to total do
                begin
                    newitem := TMyClass.Create;
                    newitem.LoadFromStream(fs); // have each item load itself
                    MyList.Add(newitem); // add it to our list
                end;
            finally
                fs.free;
            end;
        end;
    end;

procedure TForm1.SaveMyClassesToFile;
    var
        fs: TStream;
        total: integer;
        i: integer;
        newitem: TMyClass;
    begin
        if SaveDialog1.Execute then
        begin
            fs := TFileStream.Create(SaveDialog1.Filename, fmCreate);
            try
                total := MyList.Count;
                fs.Write(total, sizeof(total)); // how many objects to save to file
                for i := 0 to pred(total) do
                  TMyClass(MyList[i]).SaveToStream(fs); // have each item save itself
            finally
                fs.free;
            end;
        end;
    end;

procedure TForm1.bLoadClick(Sender: TObject);
    begin
        LoadMyClassesFromFile;
    end;

procedure TForm1.bSaveClick(Sender: TObject);
    begin
        SaveMyClassesToFile;
    end;


procedure TForm1.bAddToMyListClick(Sender: TObject);
    var
        newitem: TMyClass;
    begin
        newItem := TMyClass.Create;
        newitem.Name := eName.Text;
        newitem.Age.age := StrToIntDef(eAge.Text, 0);
        newitem.Age.dateofbirth := eDateOfBirth.Text;
        newitem.Age.cityofbirth := eCityOfBirth.Text;
        newitem.Address := eAddress.Text;
        MyList.Add(newitem);
    end;

procedure TForm1.bShowListClick(Sender: TObject);
    var
        i: integer;
    begin
        memo1.lines.clear;
        for i := 0 to pred(MyList.Count) do
          memo1.lines.add(
          TMyClass(MyList[i]).name + ' : ' +
          IntToStr(TMyClass(MyList[i]).age.age) + ' : ' +
          TMyClass(MyList[i]).age.dateofbirth + ' : ' +
          TMyClass(MyList[i]).age.cityofbirth + ' : ' +
          TMyClass(MyList[i]).address);

    end;

{ TAgeClass }

constructor TAgeClass.Create;
    begin
        age := 0;
        dateofbirth := '';
        cityofbirth := '';
    end;

end.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.