在我們編寫的每一個程序中,我們都要保存一些有用的信息,如何保存這些信息呢?比較常用的有三種方法,一種是使用注冊表,一種是使用Ini文件,還有就是使用文件。采用那種方法保存配置信息,不同的人可能有不同的習慣,這三種方法那種最適合你的程序呢,究竟那個最方便呢?
一、使用注冊表
在BCB中有個TRegistry,它提供了方便的注冊表操作,它有幾個重要的屬性和方法。如下:
__property HKEY RootKey = {read=FRootKey, write=SetRootKey, nodefault};
這個屬性用來設置和取得當前的根鍵。在默認情況下它的值是HKEY_CURRENT_USER。
這個屬性是我們常常用到的。
bool __fastcall OpenKey(const AnsiString Key, bool CanCreate);
這個方法用來打開一個鍵,bool CanCreate是表示如果這個鍵不存在則是否創建這個鍵,true是創建。如果打開成功返回true。
void __fastcall CloseKey(void);
這個方法關閉當前打開的鍵,當你完成注冊表的修改後,應該調用此方法來保存您的修改。
bool __fastcall KeyExists(const AnsiString Key);
這個方法判斷一個鍵是否存在。
bool __fastcall ValueExists(const AnsiString Name);
這個方法判斷當前鍵下是否存在指定的數據項。
AnsiString __fastcall ReadString(const AnsiString Name);
這個方法從當前鍵下指定的數據項讀取一個字符串。
void __fastcall WriteString(const AnsiString Name, const AnsiString Value);
這個方法向當前鍵下指定的數據項寫入一個字符串。類似的函數還有ReadInteger,WriteInteger,ReadBool,WriteBool等方法,這裡就不一一列舉了,請大家看一下在線幫助就可以了,下面我舉一個使用注冊表保存和讀取程序配置信息的例子來說明如何用注冊表讀取和保存程序的配置信息。
下面這個例子從HKEY_LOCAL_MACHINE\\Software\\MyInfo鍵下讀取配置信息,如果程序是第一次運行則建立這個鍵。(使用TRegistry類,需要包含Registry.hpp)
#include <Registry.hpp>
void __fastcall ReadConfig ()
{
TRegistry * reg = new TRegistry();
reg->RootKey = HKEY_LOCAL_MACHINE;
if ( reg->OpenKey ( "\\Software\\MyInfo", true ) )
{//打開HKEY_LOCAL_MACHINE\\Software\\MyInfo鍵如果不存在則創建
if ( reg->ValueExists ( "DataPath" ) )
{//判斷是否存在DataPath這個數據項,存在則讀取
SysConfig.DataPath = reg->ReadString ( "DataPath" );
}else{//如果不存在這個數據項則采用程序默認路徑
SysConfig.DataPath = DefaultPath;
}
}
reg->CloseKey();//關閉打開的鍵。
delete reg;
}
下面這個例子是保存信息到注冊表,如果不存在這個鍵則創建並保存。
void __fastcall SaveConfig ()
{
TRegistry * reg = new TRegistry();
reg->RootKey = HKEY_LOCAL_MACHINE;
if ( reg->OpenKey ( "\\Software\\MyInfo", true ) )
{//打開HKEY_LOCAL_MACHINE\\Software\\MyInfo鍵如果不存在則創建
reg->WriteString ( "DataPath", SysConfig.DataPath );
}
reg->CloseKey();//關閉打開的鍵並保存信息
delete reg;
}
這兩個例子很簡單,其它的一些讀寫方法也和讀取和寫入String差不多,大家可以試試。
使用注冊表要注意的問題。
使用注冊表保存配置信息是多數軟件所采用的方法,用注冊表的優點是用戶輕易不能夠取得和修改這些配置信息,能夠有一定的安全性和隱蔽性,如果你采用二進制方式寫入的話,用戶將很難知道你保存的數據內容,這樣可以使你的數據更安全它的缺點就是你要注意在Windows的不同版本下,注冊表的結構是不同的,而且在NT和WIN2000下,如果權限不夠有些鍵系統是不允許你訪問的。再就是用戶很討厭軟件在它的注冊表裡寫
入一些東西。這也就是流行
二、使用INI配置文件
的綠色軟件之說了。
在BCB中有個TIniFile類,它提供了對INI文件的操作,INI文件一種通用的配置文件格式它也象注冊表一樣分鍵和數據項,下面是一個INI配置文件的內容,它有一個鍵LastConfig,在這個鍵下有一個數據項DefaultDit,在數據項後面就是這個數據項的值。
[LastConfig]
DefaultDir=E:\xxx
TIniFile類有幾個常用的方法給大家介紹一下:
__fastcall TIniFile(const AnsiString FileName) : Inifiles::TCustomIniFile(FileName) { }
這個方法創建一個INI對象,如果FileName指定的文件名不存在則自動生成此文件,FileName可以用全路徑,指定INI文件的地點,如果只有文件名沒有路徑,這個函數將到Windows系統路徑下去打開或創建。(WIN9X是Windows目錄,NT和2000是WINNT目錄)
bool __fastcall SectionExists(const AnsiString Section);
這個方法判斷是否存在Section這個鍵。
virtual AnsiString __fastcall ReadString(const AnsiString Section, const AnsiString Ident, const AnsiString Default);
這個方法從INI文件中讀取一個字符串,Section是指定的鍵,Ident是指定鍵下的數據項Default是如果這個項不存在的時候的默認值。
virtual void __fastcall WriteString(const AnsiString Section, const AnsiString Ident, const AnsiString Value);
這個方法是向INI文件中寫入一個字符串,Senction是指定的鍵,Ident是指定的數據項,Value是要寫入的數據。同TRegistry一樣,TIniFile類還提供了讀取整型、布爾型,二進制等數據類型的讀寫方法,大家看看聯機幫助就可以了,用法基本一樣。下面就那上面的INI文件為例來說明一下如何有INI文件來保存配置信息和如何從INI文件中讀取數據。
下面的例子是如何從一個INI文件中讀取配置,此配置文件保存在應用程序的目錄下,如果沒有配置,則取程序所在路徑為默認值。
#include <inifiles.hpp>
void __fastcall ReadConfig ()
{
//讀取配置,
TIniFile * regKey;
AnsiString ExePath = ExtractFileName( ParamStr ( 0 ) );
regKey = new TIniFile ( ExePath + "TrimTxt.ini");
DefaultDir=regKey->ReadString("LastConfig","DefaultDir",ExePath );
delete regKey;
}
下面的例子說明如何將信息寫入INI文件
void __fastcall SaveConfig ()
{
TIniFile * regKey;
AnsiString ExePath = ExtractFileName( ParamStr ( 0 ) );
regKey = new TIniFile ( ExePath + "TrimTxt.ini");
regKey->WriteString ( "LastConfig", "DefaultDir" , DefaultDir );
delete regKey;
}
使用INI文件保存配置信息是很方便的,它最大的優點就是用戶可以手工去就改它,它通常用來保存一些不是至關重要的數據。它的缺點就是不適合保存結構比較復雜的數據,而且文件容易被破壞。
三、使用文件
使用文件來保存程序的配置,大概是現在不常用到的方法。因為對文件的操作是讓很多初學頭疼的事,但通過適當的方法,用文件保存數據還是非常方便和靈活的。
在BCB中使用文件常用的有如下幾種方式。
A、用fopen,fwrite比較傳統,但比較靈活。
B、使用Stream,如FileStream和MemoryStream,優點是比較方便。
使用文件保存數據我常用的是通過定義一個結構來進行,操作,如以下的結構
struct {
char UserName[10];//用戶名
char PassWord[16];//用戶密碼
int Level[24]; //用戶權限
}UserInfo;
這個結構用來保存程序使用者的一些信息,(我隨便定義的不一定合理,只是作個例子)如果用注冊表和INI文件來保存都很麻煩,可是如果用文件就很簡單了。下面我分別用A、B兩種方式來保存和讀取。
下面的這兩個例子用傳統的文件讀寫方式來讀寫配置文件
#include <stdio.h>
bool __fastcall ReadConfig()
{
//讀取配置文件
FILE * ptr;
AnsiString FileName=ExtractFileName(ParamStr(0))+"UserInfo.Dat";
ptr = fopen ( FileName.c_str(), "rb" );
if ( ptr == NULL )
{
ShowMessage ( "文件打開失敗!" );
return false;
}
fseek ( ptr, 0L, SEEK_END );//定位到文件尾
if ( ftell ( ptr ) != sizeof ( UserInfo ) )
{
//判斷文件是否被破壞。
ShowMessage ( "配置文件被破壞!" );
fclose ( ptr );
reutrn false;
}
fseek ( ptr, 0L, SEEK_SET );//定位到文件頭
fread ( &UserInfo, sizeof(UserInfo),1,ptr);//讀取內容到結構。
fclose ( ptr );
return true;
}
void __fastcall SaveConfig()
{
FILE * ptr;
AnsiString FileName=ExtractFileName(ParamStr(0))+"UserInfo.Dat";
ptr = fopen ( FileName.c_str(), "wb" );
if ( ptr == NULL )
{
ShowMessage ( "文件打開失敗!" );
return false;
}
fwrite (&UserInfo,sizeof(UserInfo), 1, ptr );//讀取內容到結構。
fclose (ptr);
}
這樣就完成了一個配置文件的讀寫。下面在用Stream來處理這個文件。
bool __fastcall ReadConfig ()
{
//用流來讀取,我用內存流是因為我的個人習慣,其實用文件流也是一樣的。
TMemoryStream * readStream = new TMemoryStream ();
AnsiString FileName = ExtractFileName(ParamStr(0))+"UserInfo.Dat";
readStream->LoadFromFile ( FileName );
if(readStream->Size!=sizeof( UserInfo ) )
{
ShowMessage ( "配置文件被破壞!" );
delete readStream;
reutrn false;
}
readStream->Seek ( 0, soFromBeginning );//定位到文件頭
readStream->ReadBuffer ( &UserInfo, sizeof ( UserInfo ));
//讀取文件內容到結構
delete readStream;
}
void __fastcall SaveConfig ()
{
TMemoryStream * readStream = new TMemoryStream ();
AnsiString FileName=ExtractFileName(ParamStr(0))+"UserInfo.Dat";
readStream->WriteBuffer(&UserInfo, sizeof ( UserInfo ) );
//將結構寫入流
readStream->Seek ( 0, soFromBeginning );//定位到頭
readStream->SaveToFile ( FileName );
delete readStream;
}
這樣完成了用流來讀寫數據,通過對這兩種方法的比較,用流方便一些。用文件來保存數據的缺點就是有些繁瑣,而且文件容易被刪除,但它的優點就可以保存大量、復雜的數據,這時使用注冊表和INI文件所無法完成的。
以上的三種配置文件的就我的個人觀點來看,如果不是要求安全,用文件是最好的,它最靈活,而且可以快速的讀取和寫入。這也是我最長使用的方法。當然了使用注冊表和INI文件也可以完成要求,一切就看你的喜好了。