Editing INI Files From Delphi

Working with Configuration Settings (.INI) Files

Picture of a man typing on his computer
© Jupiterimages / Stockbyte / Getty Images

INI files are text-based files used for storing an application's configuration data.

Even though Windows recommends using the Windows Registry to store application specific configuration data, in many cases, you'll find that INI files provide a quicker way for the program to access its settings. Windows itself even uses INI files, desktop.ini and boot.ini being just two examples.

One simple use of INI files, as a status saving mechanism, would be to save the size and location of a form if you want a form to reappear at its previous position.

Instead of searching through a whole database of information to find the size or location, an INI file is used instead.

More Information on the INI File Format

Initialization or Configuration Settings file (.INI) is a text file with a 64 KB limit divided into sections, each containing zero or more keys. Each key contains zero or more values.

Here's an example:

 [SectionName]
 keyname1=value
 ;comment
 keyname2=value
 

Section names are enclosed in square brackets, and must begin at the beginning of a line. Section and key names are case-insensitive (the case doesn't matter), and cannot contain spacing characters. The key name is followed by an equal sign ("="), optionally surrounded by spacing characters, which are ignored.

If the same section appears more than once in the same file, or if the same key appears more than once in the same section, then the last occurrence prevails.

A key can contain string, integer or boolean value.

Delphi IDE uses the INI file format in many cases. For example, .DSK files (desktop settings) utilize the INI format.

TIniFile Class

Delphi provides the TIniFile class, declared in the inifiles.pas unit, with methods to store and retrieve values from INI files.

Prior to working with the TIniFile methods you need to create an instance of the class:

 uses inifiles;
 ...
 var
   IniFile : TIniFile;
 begin
   IniFile := TIniFile.Create('myapp.ini') ; 

The above code creates an IniFile object and assigns 'myapp.ini' to the only property of the class - the FileName property - used to specify the name of the INI file you are to use.

The code as written above looks for the myapp.ini file in the \Windows directory. A better way to store application data is in the application's folder - just specify the full path name of the file for the Create method:

 // place the INI in the application folder,
 // let it have the application name
 // and 'ini' for extension:
 
 iniFile := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini')) ;
 

Reading From INI

The TIniFile class has several "read" methods. The ReadString reads a string value from a key, ReadInteger. ReadFloat and similar are used to read a number from a key. All "read" methods have a default value that can be used if the entry does not exist.

For example the ReadString is declared as:

function ReadString(const Section, Ident, Default: String): String; override;

Write to INI

The TIniFile has a corresponding "write" method for each "read" method. They are WriteString, WriteBool, WriteInteger, etc.

For example, if we want a program to remember the name of the last person who used it, when it was, and what the main form coordinates were, we might establish a section called Users, a keyword called Last, Date to track the information, and a section called Placement with keys TopLeftWidth, and Height.

 project1.ini

  [User]
  Last=Zarko Gajic
  Date=01/29/2009
  [Placement]
  Top=20
  Left=35
  Width=500
  Height=340
 

Note that the key named Last holds a string value, Date holds a TDateTime value, and all keys in the Placement section hold an integer value.

The OnCreate event of the main form is the perfect place to store the code needed to access the values in the application's initialization file:

 procedure TMainForm.FormCreate(Sender: TObject) ;
 var
   appINI : TIniFile;
   LastUser : string;
   LastDate : TDateTime;
 begin
   appINI := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini')) ;
   try
     //if no last user return an empty string
     LastUser := appINI.ReadString('User','Last','') ;
     //if no last date return todays date
     LastDate := appINI.ReadDate('User', 'Date', Date) ;
 
     //show the message
     ShowMessage('This program was previously used by ' + LastUser + ' on ' + DateToStr(LastDate));
 
     Top := appINI.ReadInteger('Placement','Top', Top) ;
     Left := appINI.ReadInteger('Placement','Left', Left);
     Width := appINI.ReadInteger('Placement','Width', Width);
     Height := appINI.ReadInteger('Placement','Height', Height);
   finally
     appINI.Free;
   end;
 end;
 

The main form's OnClose event is ideal for the Save INI part of the project.

 procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction) ;
 var
   appINI : TIniFile;
 begin
   appINI := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini')) ;
 try
     appINI.WriteString('User','Last','Zarko Gajic') ;
     appINI.WriteDate('User', 'Date', Date) ;
 
     with appINI, MainForm do
     begin
       WriteInteger('Placement','Top', Top) ;
       WriteInteger('Placement','Left', Left) ;
       WriteInteger('Placement','Width', Width) ;
       WriteInteger('Placement','Height', Height) ;
     end;
   finally
     appIni.Free;
   end;
 end;
 

INI Sections

The EraseSection erases an entire section of an INI file. ReadSection and ReadSections fill a TStringList object with the names of all sections (and key names) in the INI file.

INI Limitations & Downsides

The TIniFile class uses the Windows API which imposes a limit of 64 KB on INI files. If you need to store more than 64 KB of data, you should use the TMemIniFile.

Another problem might rise if you have a section with more than 8 K value. One way to solve the problem is to write your own version of the ReadSection method.