2009/04/08

[轉貼]心得分享 : 參數檔 (INI 檔) 處理

來源:心得分享 : 參數檔 (INI 檔) 處理


INI 檔應用的歷史從 Windows 3.1就已存在,雖然它也是文字檔的一種,但它利用「節區(Section)」及「識別字(KeyWord)」觀念,類似資料庫的索引,所以用來當作少量 變數資料的儲存器非常適合,除變數管理容易外尚可做程式流程控制,市售套裝軟體有用 ini 檔來控制其軟體版本例子,其主執行檔可能只有一個,但依 INI 檔設定可開放其全功能版(豪華版)與非全功能版;INI檔案 Size 雖然有 64k的限制,但已足夠存放上百個變數資料;在 32 位元系統上,正統取代 INI 機能的方法為使用 Windows Regist,但為了儲存Windows 作業系統本身的資訊,Regist已夠龐大,如果我們每個應用程式又去 Regist內挖一塊空間當作自己儲藏變數或參數的地方,會讓 Regist變得更龐大更複雜,所以筆者還是建議每個程式都使用自己的INI檔來儲存自己的變數,況且 INI檔不會被淘汰,連 Linux Kylix 下都看得到其蹤影

■ 應用實例

假設程式中需要紀錄目前發票號碼(invo_no)、交易序號(tran_no),而每次交易完都要將這兩個變數值加1,若程式從頭到尾都不關機,那沒有 問題,程式會記錄目前的發票號碼及交易序號已排到幾號;但若程式中途有關機後,下次開機,程式怎知發票號碼及交易序號已排到幾號?所以除了將變數資料存於 資料庫中外,更簡單的方法就是使用INI檔來記錄變數值,在程式重新啟動時再將變數值取回,所以該INI檔內容可能長得如下:

[Varible]
invo_no=00000005
tran_no=3

其中,用中括號刮起來的Variable就是「節區(Section)」名稱(可自訂),而其內的 INVO_NO、TRAN_NO則稱為「識別字(KeyWord)」(可自訂);不可有相同名稱的兩個節區(Section),但不同的節區中可有相同名 稱的識別字(KeyWord),取用時按節區(Section)索引分開取用,如下圖:

[Varible]
invo_no=00000005
tran_no=3

[Varible_2]
invo_no=00000007
tran_no=5

■ 程式實例

接下來我們介紹使用 INI 檔來儲存或取回變數的方法,在程式中要使用 INI 檔有幾個步驟:

1.程式開頭必須 #include "inifiles.hpp"
2.程式中首先需建立一個 INI 物件以對應實際的 INI 檔,不用時再釋放這個 INI 物件,通常 INI 檔實 體與主執行檔存在同一路徑,甚至檔名也和主執行檔相同,但副檔名則為 *.ini
3.使用 INI 物件的某些方法(Method)來存取變數,取用的方法依變數型態有下列幾種方法(假設這個 INI 物件名為 MyIni)
MyIni->ReadInteger(節區名,識別字,整數Default值);
MyIni->ReadString(節區名,識別字,字串Default值);
MyIni->ReadBool(節區名,識別字,布林Default值)
4.寫入的方法依變數型態也有下列幾種方法
MyIni->WriteInteger(節區名,識別字,欲寫入之整數變數值);
MyIni->WriteString(節區名,識別字,欲寫入之字串變數值);
MyIni->WriteBool(節區名,識別字,欲寫入之布林變數值)

以下為一完整使用INI程式碼的範例
//-------------------------------------------------------
#include
#pragma hdrstop

#include "Unit1.h"
#include "inifiles.hpp" //要 include 這個東西才有 TIniFile 類別
//-------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
TIniFile *MyIni;
//-------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//-------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
  //建立 ini 物件及實體存放路徑
  MyIni = new TIniFile(ChangeFileExt( Application->ExeName, ".ini" ) );

  //讀取變數(若變數值不存在則用自動使用 Default 值)
  Left=MyIni->ReadInteger( "Form","Left",100);
  Caption=MyIni->ReadString( "Form","Caption","Default Caption");
}
//-------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
  //將變數寫入 ini 物件
  MyIni->WriteInteger("Form","Left",Left);
  MyIni->WriteString("Form","Caption",Caption);

  // 釋放 ini 物件
  delete MyIni;
}
//-------------------------------------------------------

■ INI 物件的生命週期

在上面的程式碼中,可以看見我們把 INI 物件的建立寫在 FormCreate 事件中,而釋放 INI 物件則寫在 FormClose 事件中;事實上,變數真正寫到實體檔案中,是在INI 物件釋放的時候(也就是類似關閉檔案動作);平常則只是暫存於記憶體中,如此可減少磁碟 I/O 動作,但若程式不正常關閉,則INI 物件來不及將暫存於記憶體中的變數存檔,會導致欲存檔的變數遺失;所以為保險起見,我們可在準備寫入變數的時候才去建立 INI 物件,存入後馬上釋放 INI 物件以確保寫入實體檔案中,但這樣卻會增加磁碟I/O讀寫頻繁,其中的斟酌端看應用方向的特性。

//-------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  TIniFile *MyIni;
  MyIni = new TIniFile(ChangeFileExt( Application->ExeName, ".ini" ) );

  MyIni->WriteInteger("Form","Left",Left);
  MyIni->WriteString("Form","Caption",Caption);

  delete MyIni;
}
//-------------------------------------------------------

沒有留言:

張貼留言