利用DELPHI冲破INI文件的限制
如果需要编写绿色软件,INI文件就是保存软件设置的最佳选择,虽然INI文件是一种非常古老的文件格式,但INI仍旧有着注册表无法取代的优势。Windows已经发展到了95/98,微软却并没有对INI进行进一步的支持,希望注册表能够完全替代她。INI和纯文本文件一样有着64K的限制,64K对于一般的应用是足够的,但如果您需要编写游戏菜单或其他要求储存较大量数据的程序时,INI的尺寸限制可能成为您的烦恼,也许您会考虑采用小型数据库,但在此之前不妨先尝试使用Delphi提供的TStringList来解决问题。
首先创建一个Unit,并输入以下代码:
unit Unit1 ;
{$R-}
interface
uses Windows , Classes , Dialogs ;
type
TExtIniFile = class ( TObject ) //extiniÊÇ ±ê ×¼ INIÎÄ ¼þ µÄ À© Õ¹ ÐÍ
private
FFileName : string ;
FList : TStringList ;
Str_Temp : string ;
public
constructor Create ( constFileName : string );
function ReadString ( const Section : string ; Ident : string ; Default : string ): string ;
//¶Á È¡ ×Ö ·û ´®
function ReadInteger ( const Section : string ; Ident : string ; Default : Longint ):
Longint ;
//¶Á È¡ Êý Öµ
function ReadBoolean ( const Section : string ; Ident : string ; Default : Boolean ):
Boolean ;
//¶Á È¡ ²¼ ¶û
procedure ReadSections ( Strings : TStrings );
//¼ì Ë÷ È« ²¿ ¶Î µÄ Ãû ³Æ
procedure ReadIdents ( const Section : string ; Strings : TStrings );
//¼ì Ë÷ Ö¸ ¶¨ ¶Î ÄÚ µÄ ¼ü µÄ Ãû ³Æ
property FileName : string read FFileName ;
procedure WriteString ( const Section : string ; Ident : string ; Value : string );
//д ×Ö ·û ´®
procedure WriteInteger ( const Section : string ; Ident : string ; Value : Integer );
//д Êý Öµ
procedure WriteBoolean ( const Section : string ; Ident : string ; Value : Boolean );
//д ²¼ ¶û
end ;
implementation
uses SysUtils , Consts ;
//¶¨ Òå TExtIniFileµÄ ´´ ½¨ Ê ¼þ
constructor TExtIniFile . Create ( constFileName : string );
begin
FFileName := FileName ;
FList := TStringList . Create ;
//Èç ¹û ÎÄ ¼þ ´æ ÔÚ
if FileExists ( Filename ) then
begin
FList . LoadFromFile ( FileName );
//²å Èë ¿Õ ÐÐ £¬ Ϊ ¼ì Ë÷ Ìá ¹© ±ê ʶ
if FList . Strings [ FList . Count - 1 ] <> '' then FList . Add ( '' );
end ;
end ;
//Õ⠶Π´ú Âë ¶¨ Òå ÁË ¶Á È¡ ×Ö ·û ´® µÄ ¹ý ³Ì
function TExtIniFile . ReadString ( const Section : string ; Ident : string ; Default : string ):
string ;
var
ExtIni_I , ExtIni_Start , ExtIni_End , BufSize : Integer ;
Section_Str , Ident_Str : string ;
//TempList:TStringList;
Buffer , Pchar_Temp : Pchar ;
IdentLen : Integer ;
FindEndOK : Boolean ;
begin
//Èç ¹û ÎÄ ¼þ ´æ ÔÚ
if FileExists ( FFileName ) then
begin
FindEndOK := False ;
ExtIni_Start := - 1 ;
ExtIni_End := - 1 ;
IdentLen := Length ( Ident );
//¼ì Ë÷ È« ÎÄ £¬ ²é ÕÒ Section
for ExtIni_I := 0 to FList . Count - 1 do
begin
if UpperCase ( FList . Strings [ ExtIni_I ]) = '[' + UpperCase ( Section ) + ']' then
begin
if ExtIni_Start = - 1 then
begin
ExtIni_Start := ExtIni_I ;
end ;
end ;
end ;
//Èç ¹û ²é ÕÒ Section³É ¹¦ ifExtIni_Start>-1thenbeginForExtIni_I:=ExtIni_Start+1toFList.Count-1dobeginBufSize:=Length(FList.Strings[ExtIni_I]);GetMem(Buffer,BufSize+2);Buffer^:=chr(0);
//½Ø È¡ µÚ Ò» ¸ö ×Ö ·û strLcat(Buffer,PChar(FList.Strings[ExtIni_I]),1);
//Èç ¹û µÚ Ò» ¸ö ×Ö ·û Ϊ '['IfBuffer='['thenFindEndOK:=True;
//»ò Ϊ ¿Õ Öµ ifFList.Strings[ExtIni_I]=''thenFindEndOK:=True;
//±ê ¼Ç ¸Ã ¶Î µÄ ½á Êø ÐÐ ifFindEndOK=Truethenbeginif Ext Ini-End=-1thenbeginExtIni_End:=ExtIni_I;end;end;
//ÊÍ ·Å ÄÚ ´æ FreeMem(Buffer);end;
//¼ì Ë÷ ¼ü ForExtIni_I:=0toExtIni_End-1dobeginBufSize:=Length(FList.Strings[ExtIni_I]);GetMem(Buffer,BufSize+2);Buffer^:=chr(0);strLcat(Buffer,PChar(FList.Strings[ExtIni_I]),IdentLen+1);
//Èç ¹û ¼ì Ë÷ ³É ¹¦ ifUpperCase(String(Buffer))=UpperCase(Ident+'=')thenbegin
//¼ô ÇÐ ×Ö ·û ´® BufSize:=Length(FList.Strings[ExtIni_I]);GetMem(Pchar_Temp,BufSize+2);Pchar_Temp^:=chr(0);StrCat(Pchar_Temp,PChar(FList.Strings[ExtIni_I])+Length(Ident)+1);Str_Temp:=String(Pchar_Temp);
//ÊÍ ·Å FreeMem(Pchar_Temp);end;FreeMem(Buffer);end;end;end;
SetString ( Result , pchar ( Str_Temp ), Length ( Str_Temp ));
if trim ( Str_Temp ) = '' then
Result := Default ;
end ;
//Õ⠶Π´ú Âë ¶¨ Òå ÁË ¶Á È¡ Êý Öµ µÄ ¹ý ³Ì
end ;
function TExtIniFile . ReadInteger ( const Section : string ; Ident : string ; Default : Longint ):
Longint ;
var
IntStr : string ;
begin
try
IntStr := ReadString ( Section , Ident , '' );
if ( Length ( IntStr ) > 2 ) and ( IntStr [ 1 ] = '0' ) and (( IntStr [ 2 ] = 'X' ) or ( IntStr [ 2 ] =
'x' )) then
IntStr := '$' + Copy ( IntStr , 3 , Maxint ); Result := StrToIntDef ( IntStr , Default );
finally
Result := StrToIntDef ( IntStr , Default );
end ;
end ;
//Õ⠶Π´ú Âë ¶¨ Òå ÁË ¶Á È¡ ²¼ ¶û Öµ µÄ ¹ý ³Ì
function TExtIniFile . ReadBoolean ( const Section : string ; Ident : string ; Default :
Boolean ): Boolean ;
begin
if Trim ( ReadString ( Section , Ident , 'A ' )) = '1' then
Result := true
else
Result :=
false ; if ( Str_Temp <> '0 ' ) and ( Str_Temp <> '1' ) then Result := Default ;
end ;
//Õ⠶Π´ú Âë ¶¨ Òå ÁË ¼ì Ë÷ È« ²¿ ¶Î µÄ Ãû ³Æ µÄ ¹ý ³Ì
procedure TExtIniFile . ReadSections ( Strings : TStrings );
//varExtIni_I,BufSize:Integer;Buffer,Pchar_Temp,Pchar_Temp2,Pchar_Temp3:Pchar;FindEndOK:Boolean;
begin
//Èç ¹û ÎÄ ¼þ ´æ ÔÚ ifFileExists(FFileName)thenbeginForExtIni_I:=0toFList.Count-1dobeginBufSize:=Length(FList.Strings[ExtIni_I])+2;GetMem(Buffer,BufSize);Buffer^:=chr(0);
//½Ø È¡ µÚ Ò» ¸ö ×Ö ·û strLcat(Buffer,PChar(FList.Strings[ExtIni_I]),1);
//Èç ¹û µÚ Ò» ¸ö ×Ö ·û Ϊ '['IfBuffer='[¡¯ thenbegin//Ôò ²é ÕÒ ']'GetMem(Pchar_Temp,BufSize);Pchar_Temp^:=chr(0);StrCat(Pchar_Temp,PChar(FList.Strings[ExtIni_I])+Length(FList.Strings[ExtIni_I])-1);ifPchar_Temp=']'thenbeginGetMem(Pchar_Temp2,BufSize);Pchar_Temp2^:=chr(0);StrCat(Pchar_Temp2,PChar(FList.Strings[ExtIni_I])+1);GetMem(Pchar_Temp3,BufSize);Pchar_Temp3^:=chr(0);strLcat(Pchar_Temp3,Pchar_Temp2,Length(Pchar_Temp2)-1);
//ÔÚ ÁÐ ±í ÖÐ ¼Ó Èë ×Ö ·û ´® Strings.Add(Pchar_Temp3);FreeMem(Pchar_Temp2);FreeMem(Pchar_Temp3);end;FreeMem(Pchar_Temp);end;FreeMem(Buffer);end;end;
end ;
//Õ⠶Π´ú Âë ¶¨ Òå ÁË ¼ì Ë÷ Ö¸ ¶¨ ¶Î ÄÚ µÄ ¼ü µÄ Ãû ³Æ µÄ ¹ý ³Ì
procedure TExtIniFile . ReadIdents ( const Section : string ; Strings : TStrings );
var
ExtIni_I , ExtIni_Start , ExtIni_End , BufSize : Integer ; Section_Str , Ident_Str :
string ; TempList : TStringList ; Buffer , Pchar_Temp : Pchar ; IdentLen : Integer ; FindEndOK :
Boolean ;
begin
//Èç ¹û ÎÄ ¼þ ´æ ÔÚ ifFileExists(FFileName)thenbeginFindEndOK:=False;ExtIni_Start:=-1;ExtIni_End:=-1;
//¼ì Ë÷ È« ÎÄ £¬ ²é ÕÒ SectionForExtIni_I:=0toFList.Count-1dobeginifUpperCase(FList.Strings[ExtIni_I])='['+UpperCase(Section)+']'thenbeginifExtIni_Start=-1thenExtIni_Start:=ExtIni_I;end;end;
//Èç ¹û ²é ÕÒ Section³É ¹¦ ifExtIni_Start>-1thenbeginForExtIni_I:=ExtIni_Start+1toFList.Count-1dobeginBufSize:=Length(FList.Strings[ExtIni_I]);GetMem(Buffer,BufSize+2);Buffer^:=chr(0);
//½Ø È¡ µÚ Ò» ¸ö ×Ö ·û strLcat(Buffer,PChar(FList.Strings[ExtIni_I]),1);
//Èç ¹û µÚ Ò» ¸ö ×Ö ·û Ϊ '['IfBuffer='['thenFindEndOK:=True;
//»ò Ϊ ¿Õ Öµ ifFList.Strings[ExtIni_I]=''thenFindEndOK:=True;
//±ê ¼Ç ¸Ã ¶Î µÄ ½á Êø ÐÐ ifFindEndOK=TruethenbeginifExtIni_End=-1thenbeginExtIni_End:=ExtIni_I;end;end;
//ÊÍ ·Å ÄÚ ´æ FreeMem(Buffer);end;end;ForExtIni_I:=ExtIni_Start+1toExtIni_End-1dobegin
//²é ÕÒ '='IdentLen:=pos('=',FList.Strings[ExtIni_I]);ifIdentLen<>0thenbeginBufSize:=Length(FList.Strings[ExtIni_I]);GetMem(Buffer,BufSize+2);Buffer^:=chr(0);
//½Ø È¡ ×Ö ·û strLcat(Buffer,PChar(FList.Strings[ExtIni_I]),IdentLen-1);Strings.Add(Buffer);freemem(Buffer);end;end;end;
end ;
//Õ⠶Π´ú Âë ¶¨ Òå ÁË Ð´ Èë ×Ö ·û ´® µÄ ¹ý ³Ì
procedure TExtIniFile . WriteString ( const Section : string ; Ident : string ; Value :
string );
var
ExtIni_I , ExtIni_Start , ExtIni_End , BufSize : Integer ; Buffer : Pchar ; IdentLen :
Integer ; FindEndOK , FindOK : Boolean ;
begin
FindEndOK := False ;
FindOK := False ;
ExtIni_Start := - 1 ;
ExtIni_End := - 1 ;
IdentLen := Length ( Ident );
//Èç ¹û ÁÐ ±í °ü º¬ ÄÚ ÈÝ
if FList . Count > 0 then
begin
//¼ì Ë÷ È« ÎÄ £¬ ²é ÕÒ Section
for ExtIni_I := 0 to FList . Count - 1 do
begin
if UpperCase ( FList . Strings [ ExtIni_I ]) = '[' + UpperCase ( Section ) + ']' then
begin
if ExtIni_Start = - 1 then
begin
ExtIni_Start := ExtIni_I ;
end ;
end ;
end ;
//Èç ¹û ²é ÕÒ Section ʧ °Ü
if ExtIni_Start = - 1 then
begin
FList . Add ( '[' + Section + ']' );
ExtIni_Start := FList . Count - 1 ;
end ;
//Èç ¹û ²é ÕÒ Section ³É ¹¦
if ExtIni_Start > - 1 then
begin
for ExtIni_I := ExtIni_Start + 1 to FList . Count - 1 do
begin
BufSize := Length ( FList . Strings [ ExtIni_I ]);
GetMem ( Buffer , BufSize + 2 );
Buffer ^ := chr ( 0 );
//½Ø È¡ µÚ Ò» ¸ö ×Ö ·û
strLcat ( Buffer , PChar ( FList . Strings [ ExtIni_I ]), 1 );
//Èç ¹û µÚ Ò» ¸ö ×Ö ·û Ϊ '['
if Buffer = '[' then FindEndOK := True ;
//»ò Ϊ ¿Õ Öµ
if FList . Strings [ ExtIni_I ] = '' then FindEndOK := True ;
//±ê ¼Ç ¸Ã ¶Î µÄ ½á Êø ÐÐ
if FindEndOK = True then
begin
if ExtIni_End = - 1 then
begin
ExtIni_End := ExtIni_I ;
end ;
end ;
//ÊÍ ·Å ÄÚ ´æ
FreeMem ( Buffer );
end ;
end ;
//Èç ¹û û ÓÐ ÕÒ µ½ ¶Î µÄ ½á Êø ÐÐ
if ExtIni_End = - 1 then
FList . Add ( Ident + ' = ' + Value );
//Èç ¹û ÕÒ µ½ ¶Î µÄ ½á Êø ÐÐ
if ExtIni_End <> - 1 then
begin
//¼ì Ë÷ ¼ü
for ExtIni_I := ExtIni_Start + 1 to ExtIni_End do
begin
BufSize := Length ( FList . Strings [ ExtIni_I ]);
GetMem ( Buffer , BufSize + 2 );
Buffer ^ := chr ( 0 );
StrLcat ( Buffer , PChar ( FList . Strings [ ExtIni_I ]),
IdentLen + 1 );
//Èç ¹û ¼ì Ë÷ ³É ¹¦
if UpperCase ( string ( Buffer )) = UpperCase ( Ident + ' = ' ) then
begin
FList . Strings [ ExtIni_I ] := Ident + ' = ' + Value ;
FindOK := True ;
end ;
FreeMem ( Buffer , BufSize );
end ;
if FindOK = false then
FList . Insert ( ExtIni_End , Ident + ' = ' + Value );
end ;
end ;
if FList . Count = 0 then
begin
FList . Add ( '[' + Section + ']' );
FList . Add ( Ident + ' = ' + Value );
end ;
FList . SaveToFile ( FFileName );
end ;
procedure TExtIniFile . WriteInteger ( const Section :
string ; Ident : string ; Value : Integer );
begin
WriteString ( Section , Ident , inttostr ( Value ));
end ;
procedure TExtIniFile . WriteBoolean ( const Section :
string ; Ident : string ; Value : Boolean );
begin
if Value = true then
WriteString ( Section , Ident , '1 ' )
else
WriteString ( Section , Ident , ' 0' );
end ;
end .
完成输入后,即完成了一个叫Extinifiles的非可视组件,安装到Delphi中,即可像操作inifiles一样操作Extinifiles,不仅操作方式兼容,生成的文件也相互兼容,不同之处是Extinifiles可以支持无限大的ini文件,可以使用到任何程序中。当然也可以将他改装并编译为一个Dll文件,便可以由VB调用了。在实际使用过程中,在赛阳300A的系统下可以非常快速的操作0M~1.5M的数据,而K6-2-300的系统则可以快速的操作0M~3M的数据。
以上组件在Delphi3+中文Windows98中调试通过,经实验证明同样兼容Delphi5。这个组件和演示程序亦可通过访问http://qingyuan.csw.cnshare.net获得。(长沙 夏昆冈)