Using INI Files/pl

From Free Pascal wiki
Revision as of 18:26, 8 September 2022 by Slawek (talk | contribs) (tłumaczenie na j. polski)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

العربية (ar) Deutsch (de) English (en) español (es) suomi (fi) français (fr) polski (pl) русский (ru) 中文(中国大陆)‎ (zh_CN)

Używanie plików INI

INI Files

Basic Information

Pliki INI to pliki tekstowe, które przechowują pary klucz/wartość pogrupowane w sekcje.

Pliki INI mogą być używane do łatwego zapisywania ustawień użytkownika. Możesz ułatwić sobie z nimi pracę za pomocą modułu IniFiles i klasy TINIFile. Moduł IniFiles jest częścią FCL.

Obecnie obsługiwane są tylko pliki INI zgodne z bardziej restrykcyjnym formatem plików ini systemu Windows, w których użycie sekcji jest obowiązkowe, a komentarze mogą zaczynać się tylko od średnika. Aby uzyskać więcej ogólnych informacji o plikach ini, przeczytaj to.

Pliki INI

Pliki INI używają nawiasów do tworzenia i oznaczania Sekcji, które zawierają klucze i wartości klucza. Klucz i odpowiadająca mu wartość są oddzielone znakiem równości (Klucz=Wartość).

Nazwy sekcji umieszczane są w nawiasach kwadratowych ([Sekcja]).

Komentarze są dozwolone i są oznaczone średnikiem (;) na początku linii.

Przykładowy plik ini:

; Komentarz. Początek pliku INI

; puste wiersze są ignorowane

[General]
; Tu rozpoczyna się sekcja ogólna
Compiler=FreePascal
; Key Compiler and value FreePascal
; Kompilator kluczy i wartość FreePascal


Prosty przykład

W praktyce musisz mieć możliwość utworzenia pliku ini w czasie wykonywania programu, gdy on nie istnieje, i ustawienia domyślnych wartości wpisów. Oto przykład przeznaczony do częściowego wklejenia do nowej aplikacji Lazarus. Definiujemy i deklarujemy rekord, który zawiera niektóre z naszych ustawień, mamy pole wyboru, które reprezentuje inne ustawienie. Aby uprościć, jedynym ustawieniem, które możemy tutaj zmienić, jest pole wyboru. Jego zdarzenie wywoływane „przy zmianie” wartości, wyzwala zapis pliku ini, za każdym razem aktualizując dane. Do formularza dodaliśmy również pole Memo, aby w łatwy sposób pokazać, co się dzieje. Dodane są prototypy nowych metod do interfejsu formularza. Dodany jest moduł 'inifiles' w sekcji implementacji.

interface
.......

type SettingRec = record
    X : integer;
    MyName : string;
end; 
....

implementation  
....
uses IniFiles;
const
  IniFile = 'settings.ini';   
....
procedure TForm1.ReadSettings;
var
    Sett : TIniFile;
begin
    Sett := TIniFile.Create(IniFile);
    Settings.X:= Sett.ReadInteger('Main', 'X', 1);    // (Sekcja, Klucz, Domyślna)
    Settings.MyName := Sett.ReadString('Main', 'MyName', 'Davo');
    CheckBox1.Checked := Sett.ReadBool('Main', 'CheckBox', true);
    Sett.Free;
end;

procedure TForm1.WriteSettings;
var
    Sett : TIniFile;
begin
    Sett := TIniFile.Create(IniFile);
    Sett.WriteBool('Main', 'CheckBox', CheckBox1.Checked);
    Sett.WriteInteger('Main', 'X', Settings.X);
    Sett.WriteString('Main', 'MyName', Settings.MyName);
    Sett.Free;
end;

Zauważ, że nie sprawdzamy, czy plik ini jest obecny, czy nie, to nie ma znaczenia. Jeśli nie ma określonego klucza (lub nie ma całego pliku), to podczas odczytu używana jest wartość domyślna, więc użyj domyślnej, która działa na początku. Wszystkie nasze dane są zapisywane i odczytywane z sekcji „Main” pliku ini. Warto jest pogrupować powiązane ze sobą dane w osobne sekcje. Rzeczywista nazwa sekcji nie ma znaczenia, ale musi być spójna.

Następnie potrzebujemy kilku metod, aby „przećwiczyć” powyższy kod. Oczywiście, możesz użyć używasz Lazarus Object Inspector do tworzenia FormCreate() i CheckBeSillyChange(), ale ich zawartość skopiuj stąd:

procedure TForm1.FormCreate(Sender: TObject);
begin
    ReadSettings;
    ShowSettings;
end;

procedure TForm1.CheckBox1Change(Sender: TObject);
begin
    WriteSettings;
    ShowSettings;
end;

procedure TForm1.ShowSettings;
begin
    Memo1.Clear;
    Memo1.Append('X=' + Settings.X.tostring);
    Memo1.Append('MyName=' + Settings.MyName);
    Memo1.Append('CheckBox ' + Booltostr(CheckBox1.Checked, true));
end;

procedure TForm1.CheckBox1Change(Sender: TObject);
begin
    WriteSettings;
    ShowSettings;
end;

Plik ini może (i musi mieć możliwość) zmienić kolejność prezentowania jego danych, więc nie można polegać na konkretnych numerach wierszy. Template:Uwaga

Ini file reading example

The console application below shows how to read ini files. To test it, create an ini file with the name "DB.ini" and the contents below, and save it in the same folder as the executable program.

[DB-INFO]
Author=Adam
Pass=secret
MaxAttempts=5
DBFile=C:\Money.dat

The code to read this ini file:

Program IniReadExample;

{$mode objfpc}{$H+}

uses
  classes, sysutils, IniFiles;

const
  C_DB_SECTION = 'DB-INFO';

var
  INI: TINIFile;
  Author, Pass, DBFile: String;
  MaxAttempts: integer;
  PassEnter: String;
  TryCount: integer;
begin
  // Create the object, specifying the the ini file that contains the settings
  INI := TINIFile.Create('DB.ini');

  // Put reading the INI file inside a try/finally block to prevent memory leaks
  try
    // Demonstrates reading values from the INI file.
    Author      := INI.ReadString(C_DB_SECTION,'Author','');
    Pass        := INI.ReadString(C_DB_SECTION,'Pass','');
    DBFile      := INI.ReadString(C_DB_SECTION,'DBFile','');
    MaxAttempts := INI.ReadInteger(C_DB_SECTION,'MaxAttempts',1);

    // Do something with the values read; e.g. verify the password
    if Pass <> '' then
    begin
      // Ask for the password, max attempts = MaxAttempts
      TryCount := MaxAttempts;
      repeat
        write('Please enter password; ', TryCount, ' attempt(s) left: ');
        readln(PassEnter);
        dec(TryCount);
        if (PassEnter <> Pass) and (TryCount > 0) then
          writeln('Wrong Password, please try again');
      until(PassEnter = Pass) or (TryCount = 0);

      // Correct password given?
      if PassEnter = Pass then
        writeln('Correct Password.')
      else
        writeln('Invalid password, but maxiumm number of password attempts reached.');
    end;

    writeln('Author               : ', Author);
    writeln('File                 : ', DBFile);
    writeln('Password             : ', Pass);
    writeln('Max password attempts: ', MaxAttempts);
    writeln;
    write('Press Enter to close...');
    Readln;

  finally
    // After the ini file was used it must be freed to prevent memory leaks.
    INI.Free;
  end;
end.

Handling of string representations of boolean values

The TiniFile.ReadBool and TIniFile.WriteBool functions use values of "0" (false) and "1" to represent boolean values in the ini file. You can change this to any other text you want:

[...]
  iniFile.Options := iniFile.Options + [ifoWriteStringBoolean];
  iniFile.BoolTrueStrings := ['true'];
  iniFile.BoolFalseStrings := ['false'];
[...]

ReadBool is not case-sensitive, the texts "true", "True" and "TRUE" are all interpreted as boolean true.

TIniFile.BoolTrueStrings and TIniFile.BoolFalseStrings are arrays of string, you can specify multiple values:

[...]
  iniFile.Options := iniFile.Options + [ifoWriteStringBoolean];
  iniFile.BoolTrueStrings := ['true','yes','1'];
  iniFile.BoolFalseStrings := ['false','no','0'];
[...]

When reading from the ini file, any of the array values will make ReadBool return the correct boolean value, when writing the ini file, the first value of the corresponding array is used.

Warning-icon.png

Ostrzeżenie: The current implementation if TIniFile.ReadBool has an odd behaviour, when the ifoWriteStringBoolean option is set. TIniFile.ReadBool and TIniFile.WriteBool have, when the BoolTrueStrings and BoolFalseStrings arrays are not specified, an asymmetrical behaviour: TIniFile.ReadBool will expect "0" or "1", and TIniFile.WriteBool will write "true" or "false". This will lead to the surprising behavior that the TIniFile.ReadBool function won't be able to read back the "true" values if they were written by the TIniFile.WriteBool function. TIniFile.ReadBool will always return boolean false instead, even if a value is set to "true" in the ini file. If you use the ifoWriteStringBoolean option, and unless this behavior is the desired behaviour, don't forget to specify the TIniFile.BoolTrueStrings and TIniFile.BoolFalseStrings arrays.

Objects to know

In the TINIFile class there are many different properties, procedures and functions that can be used.

CaseSensitive - This property allows you to say if the keys and sections are case sensitive or not. By default they aren't.

ReadString - Has 3 constant statements. The first one is the section to search in. The second one is the key to look for. The third one is a default string in case the key and/or section searched for is not found.

WriteString - has three constant statements, too. The first is the section. The second is the key and the last is the value that you want to write. If the key and section exist already, the key will be overwritten with the new value..

ReadSections - Will allow you to to take the sections from the INI file and put them in a TStrings class (or TStringList with the AS operator).

DeleteKey - Remove an existing key from a specific section.

EraseSection - Remove a section and all its data.

There are more procedures and functions but this is enough to get you started.

Reference Documentation

Here: Free Pascal documentation on INI files

See also