首页  编辑  

利用DELPHI冲破INI文件的限制

Tags: /超级猛料/Registry.注册表和INI/   Date Created:

利用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获得。(长沙 夏昆冈)