Using INI Files/pl

From Free Pascal wiki
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

Przykład odczytu pliku ini

Poniższa aplikacja konsolowa pokazuje, jak czytać pliki ini. Aby to przetestować, utwórz plik ini o nazwie „DB.ini” i zawartości jak podano poniżej, a następnie zapisz go w tym samym folderze co program wykonywalny.

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

Kod do odczytu tego pliku ini wygląda tak:

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
  // Utwórz obiekt, określając plik ini, który zawiera ustawienia
  INI := TINIFile.Create('DB.ini');

  // Umieść kod odczytujący plik INI w bloku try/finally, aby zapobiec wyciekom pamięci
  try
    // Demonstruje odczytywanie wartości z pliku INI.
    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);

    // Zrób coś z odczytanymi wartościami; np. zweryfikuj hasło
    if Pass <> '' then
    begin
      // Zapytaj o hasło, maksymalna ilość prób = MaxAttempts
      TryCount := MaxAttempts;
      repeat
        write('Proszę wprowadzić hasło; ', TryCount, ' pozostało prób: ');
        readln(PassEnter);
        dec(TryCount);
        if (PassEnter <> Pass) and (TryCount > 0) then
          writeln('Błędne hasło, spróbuj ponownie');
      until(PassEnter = Pass) or (TryCount = 0);

      // Czy podano prawidłowe hasło?
      if PassEnter = Pass then
        writeln('Hasło jest prawidłowe.')
      else
        writeln('Nieprawidłowe hasło i osiągnięto maksymalną liczbę prób hasła.');
    end;

    writeln('Autor                       : ', Author);
    writeln('Plik                        : ', DBFile);
    writeln('Hasło                       : ', Pass);
    writeln('Maksymalna liczba prób hasła: ', MaxAttempts);
    writeln;
    write('Naciśnij Enter, aby zamknąć...');
    Readln;

  finally
    // Po użyciu pliku ini należy go zwolnić, aby zapobiec wyciekom pamięci.
    INI.Free;
  end;
end.

Obsługa reprezentacji ciągów wartości logicznych

Funkcje TiniFile.ReadBool i TIniFile.WriteBool używają wartości „0” (fałsz) i „1” do reprezentowania wartości logicznych w pliku ini. Możesz to zmienić na dowolny inny tekst:

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

ReadBool nie rozróżnia wielkości liter, teksty „true”, „true” i „TRUE” są interpretowane jako prawda logiczna.

TIniFile.BoolTrueStrings i TIniFile.BoolFalseStrings to tablice łańcuchów, można określić wiele wartości:

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

Podczas odczytu z pliku ini, każda z wartości tablicy spowoduje, że ReadBool zwróci poprawną wartość logiczną, podczas zapisywania pliku ini używana jest pierwsza wartość odpowiedniej tablicy.

Warning-icon.png

Ostrzeżenie: Aktualna implementacja TIniFile.ReadBool działa tak, że zachowuje się dziwnie, gdy ustawiona jest opcja ifoWriteStringBoolean. Gdy nie określono tablic BoolTrueStrings i BoolFalseStrings, to TIniFile.ReadBool i TIniFile.WriteBool zachowują się asymetryczne: TIniFile.ReadBool będzie oczekiwać „0” lub „1”, a TIniFile.WriteBool zapisze „true” lub „false”. Doprowadzi to do zaskakującego zachowania polegającego na tym, że funkcja TIniFile.ReadBool nie będzie w stanie odczytać z powrotem wartości „true”, jeśli zostały zapisane przez funkcję TIniFile.WriteBool. TIniFile.ReadBool w tej sytuacji zawsze zwróci wartość logiczną false, nawet jeśli w pliku ini wartość ta jest ustawiona na „true”. Jeśli używasz opcji ifoWriteStringBoolean i to zachowanie nie jest pożądanym zachowaniem, nie zapomnij określić tablic TIniFile.BoolTrueStrings i TIniFile.BoolFalseStrings.

Obiekty do poznania

W klasie TINIFile istnieje wiele różnych właściwości, procedur i funkcji, których można użyć.

CaseSensitive - Ta właściwość pozwala określić, czy w kluczach i sekcjach jest rozróżniana wielkość liter, czy nie. Domyślnie nie są.

ReadString - Ma 3 stałe parametry. Pierwszy to sekcja, w której należy szukać. Drugi jest kluczem do wyszukania. Trzeci jest domyślnym ciągiem na wypadek, gdyby szukany klucz i/lub sekcja nie zostały znalezione.

WriteString - Również zawiera trzy stałe parametry. Pierwszy to sekcja. Drugi to klucz, a ostatni to wartość, którą chcesz wpisać. Jeśli klucz i sekcja już istnieją, klucz zostanie nadpisany nową wartością.

ReadSections - Pozwala pobrać sekcje z pliku INI i umieścić je w klasie TStrings (lub TStringList z operatorem AS).

DeleteKey - Usuń istniejący klucz z określonej sekcji.

EraseSection - Usuń sekcję i wszystkie jej dane.

Procedur i funkcji jest więcej, ale to wystarczy, aby zacząć.

Dokumentacja referencyjna

Tutaj jest: Dokumentacja Free Pascal na temat plików INI

Zobacz także