Obsługa Plików Ini.

  1. Szybki zapis profilu do pliki *.ini

 

    Zapewne każdy zetknął się lub wcześniej czy później zetknie się z plikami służącymi do zapisywania konfiguracji programów. Mam na myśli oczywiście pliki ustawiania konfiguracji posiadające rozszerzenie *.ini. Pliki o których piszę wyglądają mniej więcej tak:

[NAZWA SEKCJI]
Nazwa wartości=wartość określonego typu

Nazwa sekcji to identyfikator na podstawie którego można określić położenie określonych ustawień.
Nazwa wartości to identyfikator na podstawie którego można określić położenie konkretnych wartości wewnątrz określonej wcześniej sekcji.
Wartość określonego typu to wartość będąca parametrem przechowującym jakieś wartości. Skupię się na  trzech najczęściej wykorzystywanych typach wartości, mianowicie wartości znakowe do przechowywania tekstu, wartości liczbowe do przechowywania liczb, wartości typu bool służące do przechowywania wartości logicznych: 0 - fałsz & 1 - prawda.
    Na razie może się to wydawać trochę skomplikowane, jednak korzystanie z plików ini jest bardzo proste i ogranicza się w zasadzie do określenia nazwy sekcji, nazwy wartości i zadanych parametrów. Zanim jednak zaczniemy korzystać z tego typu plików należy włączyć do projektu aplikacji w pliku nagłówkowym, w sekcji include plik inifiles.hpp:

// Plik nagłówkowy np. Unit1.h
 //--------------------------------
 #ifndef Unit2H
 #define Unit2H

 //--------------------------------
 #include <Classes.hpp>
 #include <Controls.hpp>
 #include <StdCtrls.hpp>
 #include <Forms.hpp>
 #include "CSPIN.h"
 #include <Dialogs.hpp>
 #include <inifiles.hpp>
 
//--------------------------------

Następnie trzeba stworzyć nowy obiekt typy TIniFile. Jeżeli chcemy żeby obiekt był dostępny dla całej aplikacji trzeba go najpierw zadeklarować w pliku nagłówkowym w sekcji private lub public, a następnie zdefiniować w pliku źródłowym w konstruktorze klasy TForm. Pójdę na łatwiznę i wszystkie przykłady wykorzystania obiektu typu TIniFile będę przedstawiał w kontekście zdarzenia OnClick dla przycisku Button1.
Tak więc deklarujemy i definiujemy nowy obiekt typu TIniFile:

// Plik źródłowy np. Unit1.cpp
//--------------------------------
void __fastcall TForm1::Button1Click(TObject* Sender)
{
 TIniFile *PlikIni = new TIniFile("Nazwa_pliku.ini");
}
//---------------------------------

Jak widać w przykładzie cała definicja ogranicza się do podania nazwy obiektu (w przykładzie - PlikIni - przy czym nazwa jest dowolna), oraz do określenia nazwy pliku który zawiera ustawienia programu lub do którego chcemy te ustawienia zapisać. Na początek pokażę jak należy zapisywać parametry do pliku ini (po jednym parametrze każdego typu). W tym celu umieszczamy na formularzu (np. Form1) obiekt Edit1 oraz obiekt CheckBox1, a następnie zapiszemy do pliki ini zawartość właściwości Text obiektu Edit1, właściwość Checked obiektu CheckBox1 oraz szerokość i wysokość formularza Form1:

// Plik źródłowy np. Unit1.cpp
//--------------------------------
void __fastcall TForm1::Button1Click(TObject* Sender)
{
 TIniFile *Ini = new TIniFile("Ustawienia.ini");

 Ini->WriteString("SEKCJA1", "ZawartoscEdit1", Edit1->Text);          // zapisywanie tekstu do sekcji [SEKCJA1].
 Ini->WriteBool("SEKCJA1", "UstawieniaCheckBox1", CheckBox1->Checked);// zapisywanie wartości true/false do sekcji [SEKCJA1].
 Ini->WriteInteger("SEKCJA1", "SzerokoscForm1", Width);               // zapisywanie wartości liczbowej do sekcji [SEKCJA1].
 Ini->WriteInteger("SEKCJA1", "WysokoscForm1", Height);               // zapisywanie wartości liczbowej do sekcji [SEKCJA1].   

 delete Ini;
}
//---------------------------------

Jak to widać w przykładzie cała sztuka polega na wykorzystaniu trzech funkcji:

  1. WriteString    -    zapisuje do pliku w podanej sekcji i podsekcji tekst.
  2. WriteBool      -    zapisuje do pliku w podanej sekcji i podsekcji wartości logiczne typu prawda lub fałsz.
  3. WriteInteger  -    zapisuje do pliku w podanej sekcji i podsekcji wartości liczbowe całkowite.

Podany przykład utworzy następujący plik:

[SEKCJA1]
ZawartoscEdit1=Edit1
UstawieniaCheckBox1=0
SzerokoscForm1=800
WysokoscForm1=600

Chcąc odczytać wartości z pliku ini trzeba postąpić odwrotnie do zapisywania i posłużyć się funkcjami:

  1. ReadString    -    odczytuje z pliku tekst z podanej sekcji i podsekcji.
  2. ReadBool      -    odczytuje z pliku wartości logiczne typu prawda lub fałsz z podanej sekcji i podsekcji.
  3. ReadInteger  -    odczytuje z pliku wartości liczbowe całkowite z podanej sekcji i podsekcji.

Przy odczytywaniu danych występuje jednak pewien dodatkowy element, a mianowicie wartość domyślna, czyli jeżeli próba odczytania zawartości z pliku ini się nie powiedzie, wtedy zostaną użyte podane wartości domyślne:

// Plik źródłowy np. Unit1.cpp
//--------------------------------
void __fastcall TForm1::Button1Click(TObject* Sender)
{
 TIniFile *Ini = new TIniFile("Ustawienia.ini");

 Edit1->Text = Ini->ReadString("SEKCJA1", "ZawartoscEdit1", "tekst domyślny"); // odczytywanie tekstu z sekcji [SEKCJA1].
 CheckBox1->Checked = Ini->ReadBool("SEKCJA1", "UstawieniaCheckBox1", false);  // odczytywanie wartości true/false z sekcji [SEKCJA1].
 Form1->Width = Ini->ReadInteger("SEKCJA1", "SzerokoscForm1", 800);            // odczytywanie wartości liczbowej z sekcji [SEKCJA1].
 Form1->Height = Ini->ReadInteger("SEKCJA1", "WysokoscForm1", 600);            // odczytywanie wartości liczbowej z sekcji [SEKCJA1].

 delete Ini;  
}
//---------------------------------

W zasadzie to już prawie wszystko, na zakończenie podam jeszcze inne rzadziej stosowane funkcje obiektu TIniFile:

Opracował: Cyfrowy Baron

Szybki zapis profilu do pliku *.ini.

Jak zapisywać różnego typu wartości do plików INI jest opisane wyżej, w tej poradzie chcę przedstawić dwie funkcje, które pozwalają na zapisanie wartości typu String do pliku INI bez włączania do projektu biblioteki IniFiles.hpp, ale oczywiście nie to jest zaletą tych funkcji lecz łatwość ich stosowania bez tworzenia kodu, są to funkcje WriteProfileString(SEKCJA, KLUCZ, WARTOŚĆ STRING), funkcja ta zapisuje dane do pliku Win.ini znajdującego się w katalogu Windows i nie można tego zmienić, natomiast druga funkcja: WritePrivateProfileString(SEKCJA, KLUCZ, WARTOŚĆ STRING, NAZWA PLIKU) pozwala na zdefiniowanie pliku do którego chcemy zapisać dane, jeżeli podamy tylko nazwę pliku bez ścieżki dostępu, to taki plik zostanie zapisany w katalogu Windows:

// Plik źródłowy np. Unit1.cpp.
//--------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
 WriteProfileString("PROFIL", "KLUCZ", "wartość typu String");
}
//--------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
 WritePrivateProfileString("PROFIL", "KLUCZ", "wartość typu String", "nazwa pliku.ini");
}
//--------------------------------

Niestety nie istnieją funkcje pozwalające na równie szybki odczyt tych danych, w przykładzie pokażę jak stworzyć własną funkcję odczytującą dane z pliku Win.ini, oczywiście zasada jest taka sama, jak przy tworzeniu plików ini i w zasadzie na tym się opiera:

// Plik źródłowy np. Unit1.cpp.
#include <Inifiles.hpp>
//--------------------------------
AnsiString ReadProfileString(String Profil, String Klucz)
{
 char winini[_MAX_PATH];
 GetWindowsDirectory(winini, _MAX_PATH);
 
 TIniFile *Ini = new TIniFile((AnsiString)winini + "\\Win.ini");
 String Value = Ini->ReadString(Profil, Klucz, "");
 Ini->Free();
 
 return Value;
}
//--------------------------------
void __fastcall TForm1::Button5Click(TObject *Sender)
{
 Label4->Caption = ReadProfileString("PROFIL", "KLUCZ");
}
//--------------------------------

Jak widać tym razem należy włączyć do projektu bibliotekę IniFiles.hpp.