Jump to content




Recent Status Updates

View All Updates

Binpress - Cut your development time and costs in half
Photo
- - - - -

Working With INI Files in Delphi

delphi

  • Please log in to reply
No replies to this topic

#1 Luthfi

Luthfi

    CC Leader

  • Expert Member
  • PipPipPipPipPipPipPip
  • 1,318 posts
  • Programming Language:PHP, Delphi/Object Pascal, Pascal, Transact-SQL
  • Learning:C, Java, PHP

Posted 12 March 2011 - 06:27 AM

Overview

INI files are simply text files with a format in order to save data in name and value pairs. The name an value pair also usually called property. Properties are grouped into sections, to make INI files able to hold duplicate names as long as the names are unique in the given section.

[ATTACH]3785[/ATTACH]

Above is a sample of an INI file. The INI file’s name is myini.ini (I know, not very intuitive name, but I hope it serves the purpose :c-whistle:). This INI file contains three sections: TForm1, TForm2, and TForm3. As you can see, a section is started by the section name wrapped by square brackets. The section goes until another section starts or meeting the end of file.

Name and values are separated by equal sign (=). Everything (in a property) before the equal sign are names, and everything (in a property) after the equal sign are values. Some also refer to names as identifiers. So don’t get confused if I mix the terms in the future. For example, in section number 1 (TForm1) we have a line

Caption=Caption Number 3

. For this line, Caption is the name and "Caption Number 3" is the value.

Limitations

Since INI file's main purpose was only to hold configuration data, it has some limitations compared to some other file format.
  • Only one line for each name and value pair. Line in this case is marked by CR (Carriage Return, ascii #13) and LF (Line Feed, ascii #10) pair. So you cannot store multiple lines value with a name.
    If you need to store multiple lines, then you have to break it into several pairs of name-values.
  • No binary data. Since it is text file, you cannot directly store arbitrary binary value. But you can store text format of the binary values and do conversions when reading or writing. For example you can use hexadecimal or Base64 format.


Reading and Writing INI Files with Delphi

To handle INI files, Delphi had provided a class specifically for this purpose. The class' name is TIniFile, declared in IniFiles unit. This class even allows you to store binary values into the ini file (it handles the conversion to and from hexadecimal automatically, the only catch is that it limits the max size of the binary values to 1023 bytes).

Reading a Single Value

TIniFile provides many methods to read a single value. The basic use is pretty much the same. The main difference is only the value type they assigned for.

Basic Use:
AVariable := TIniFile.ReadXXXX(ASectionName, ATheName, ADefaultValue);
Note:
  • ASectionName: The section name from which we want to retrieve the value.
  • ATheName: The name of the value to retrieve
  • ADefaultValue: This value will be returned if the section is or the name is not found.
  • ReadXXXX can be one of the following methods (XXXX relates with the value type):
  • ReadString
  • ReadInteger
  • ReadBool
  • ReadFloat
  • ReadDateTime
  • ReadDate
  • ReadTime
  • ReadBinaryStream

Writing a Single Value

To store a single value, TIniFile has already provided methods according to value type.

Basic Use:
TIniFile.WriteXXXX(ASectionName, ATheName, AValue);
Note:
  • ASectionName: The section name to which we want to store the value.
  • ATheName: The name of the value to be stored
  • AValue: The value to be stored
  • WriteXXXX can be one of the following methods (XXXX relates with the value type):
  • WriteString
  • WriteInteger
  • WriteBool
  • WriteFloat
  • WriteDateTime
  • WriteDate
  • WriteTime
  • WriteBinaryStream

Getting Names of Sections

To get the names of all sections in an INI file, we can use method ReadSections of TIniFile. E.g.:

uses
  ...
  , IniFiles
  ...
  ;

procedure GetSectionNames(ASections: TStrings);
var
  vIni: TIniFile;
begin
  vIni := TIniFile.Create(IniFileName);
  try
    vIni.ReadSections(ASections);
  finally
    vIni.Free;
  end;
end;

Reading All Values of a Section

We can also read all values stored in a section. For this we will need to pass an valid instance of TStrings to contain the values. All values are in text format.

uses
  ...
  , IniFiles
  ...
  ;

procedure GetValuesOfSection(const ASection: string; AValues: TStrings);
var
  vIni: TIniFile;
begin
  vIni := TIniFile.Create(IniFileName);
  try
    vIni.ReadSectionValues(ASection, AValues);
  finally
    vIni.Free;
  end;
end;

When the method returns, AValues will be filled with name value pairs contained by the specified section.

Checking Availability of Values

Sometimes we need to know exactly whether a value or a section is really exists. To check existence of a section we can use SectionExists method by passing the section name to it. And to check a value we can use ValueExists method by passing the section and the name of the value.


Implementation (Demo)

In the demo project we want to store the "content" of our form to an INI file when we close the application, so that the next time it runs it will show the last content. The key methods are:

  private
    function IniFile: string;
  public
    procedure ReadIniFile;
    procedure SaveToIni;

Function IniFile

function IniFile is "calculating" the file name for our INI file. It returns ini file with the name "myini.ini" from the same location with our program.

function TForm1.IniFile: string;
begin
  Result := ExtractFilePath(ParamStr(0)) + 'myini.ini';
end;

Procedure ReadIniFile
This procedure reads information from our INI file into corresponding controls.

procedure TForm1.ReadIniFile;
var
  vIni: TIniFile;
  S   : TStream;
  vBmp: TBitmap;
begin
  vIni := TIniFile.Create(IniFile);
  try
    Self.Caption := vIni.ReadString(Self.ClassName, 'Caption', '');
    lblHeader.Caption := vIni.ReadString(Self.ClassName, 'Header', '');
    Memo1.Text := vIni.ReadString(Self.ClassName, 'Memo', '');
    cbbOption.ItemIndex := vIni.ReadInteger(Self.ClassName, 'Option', -1);
    S := TMemoryStream.Create;
    try
      vIni.ReadBinaryStream(Self.ClassName, 'Picture', S);
      if S.Size > 0 then
      begin
        S.Position := 0;
        vBmp := TBitmap.Create;
        try
          vBmp.LoadFromStream(S);
          Image1.Picture.Graphic := vBmp;
        finally
          vBmp.Free;
        end;
      end
      else
        Image1.Picture.Graphic := nil;
    finally
      S.Free;
    end;
  finally
    vIni.Free;
  end;
end;

Please note that the ability to load bitmap graphic here is only for illustration purpose. I don't recommend to store graphics or any other large size values into INI files.


Procedure SaveToIni

This procedure stores the content of our controls into the INI file.

procedure TForm1.SaveToIni;
var
  vIni: TIniFile;
  S   : TStream;
begin
  vIni := TIniFile.Create(IniFile);
  try
    vIni.WriteString(Self.ClassName, 'Caption', Self.Caption);
    vIni.WriteString(Self.ClassName, 'Header', lblHeader.Caption);
    vIni.WriteString(Self.ClassName, 'Memo', Memo1.Text);
    vIni.WriteInteger(Self.ClassName, 'Option', cbbOption.ItemIndex);
    vIni.ValueExists()
    S := TMemoryStream.Create;
    try
      if Assigned(Image1.Picture.Graphic) then
      begin
        Image1.Picture.Graphic.SaveToStream(S);
        S.Position := 0;
      end;
      vIni.WriteBinaryStream(Self.ClassName, 'Picture', S);
    finally
      S.Free;
    end;
  finally
    vIni.Free;
  end;
end;

To automatically read the INI file when starting, place ReadIniFile in OnCreate event of the form. To automatically store content into INI file when closing, place SaveToIni in OnClose event of the form. And now it's ready.

Full source code of the demo project is attached. Feel free to use or improve it. Just note that the "store bitmap" feature is just for illustration of storing binary values. It will fail to load if you try to store bitmap image with size over 1023 bytes (TIniFile.WriteBinaryStream self imposed limitation). Again, I don't recommend to store large size values in INI files.

[ATTACH]3786[/ATTACH]

Attached Images

  • IniFileStructure_001.png

Attached Files


Edited by LuthfiHakim, 12 March 2011 - 09:10 AM.

  • 0





Powered by binpress