[转载]利用DELPHI冲破INI文件的限制
Writer:夏昆冈[quote]利用DELPHI冲破INI文件的限制
如果需要编写绿色软件,INI文件就是保存软件设置的最佳选择,虽然INI文件是一种非常古老的文件格式,但INI仍旧有着注册表无法取代的优势。Windows已经发展到了95/98,微软却并没有对INI进行进一步的支持,希望注册表能够完全替代她。INI和纯文本文件一样有着64K的限制,64K对于一般的应用是足够的,但如果您需要编写游戏菜单或其他要求储存较大量数据的程序时,INI的尺寸限制可能成为您的烦恼,也许您会考虑采用小型数据库,但在此之前不妨先尝试使用Delphi提供的TStringList来解决问题。
首先创建一个Unit,并输入以下代码:
[code] unit Unit1;
{$R-}
interface
uses Windows, Classes, Dialogs;
type
TExtIniFile = class(TObject) //extiniê? ±ê ×? INI?? ?t μ? à? ?1 Dí
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;
//?á è? êy ?μ
function ReadBoolean(const Section: string; Ident: string; Default: Boolean):
Boolean;
//?á è? 2? ??
procedure ReadSections(Strings: TStrings);
//?ì ?÷ è? 2? ?? μ? ?? 3?
procedure ReadIdents(const Section: string; Strings: TStrings);
//?ì ?÷ ?? ?¨ ?? ?ú μ? ?ü μ? ?? 3?
property FileName: string read FFileName;
procedure WriteString(const Section: string; Ident: string; Value: string);
//D′ ×? ·? ′?
procedure WriteInteger(const Section: string; Ident: string; Value: Integer);
//D′ êy ?μ
procedure WriteBoolean(const Section: string; Ident: string; Value: Boolean);
//D′ 2? ??
end;
implementation
uses SysUtils, Consts;
//?¨ ò? TExtIniFileμ? ′′ ?¨ ê? ?t
constructor TExtIniFile.Create(constFileName: string);
begin
FFileName := FileName;
FList := TStringList.Create;
//è? 1? ?? ?t ′? ?ú
if FileExists(Filename) then
begin
FList.LoadFromFile(FileName);
//2? è? ?? DD £? ?a ?ì ?÷ ìá 1? ±ê ê?
if FList.Strings[FList.Count - 1] <> '' then FList.Add('');
end;
end;
//?a ?? ′ú ?? ?¨ ò? á? ?á è? ×? ·? ′? μ? 1y 3ì
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
//è? 1? ?? ?t ′? ?ú
if FileExists(FFileName) then
begin
FindEndOK := False;
ExtIni_Start := -1;
ExtIni_End := -1;
IdentLen := Length(Ident);
//?ì ?÷ è? ?? £? 2é ?ò 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;
//è? 1? 2é ?ò Section3é 1| 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);
//è? 1? μú ò? ?? ×? ·? ?a '['IfBuffer='['thenFindEndOK:=True;
//?ò ?a ?? ?μ ifFList.Strings[ExtIni_I]=''thenFindEndOK:=True;
//±ê ?? ?? ?? μ? ?á ê? DD 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);
//è? 1? ?ì ?÷ 3é 1| ifUpperCase(String(Buffer))=UpperCase(Ident+'=')thenbegin
//?? ?D ×? ·? ′? 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;
//?a ?? ′ú ?? ?¨ ò? á? ?á è? êy ?μ μ? 1y 3ì
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;
//?a ?? ′ú ?? ?¨ ò? á? ?á è? 2? ?? ?μ μ? 1y 3ì
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;
//?a ?? ′ú ?? ?¨ ò? á? ?ì ?÷ è? 2? ?? μ? ?? 3? μ? 1y 3ì
procedure TExtIniFile.ReadSections(Strings: TStrings);
//varExtIni_I,BufSize:Integer;Buffer,Pchar_Temp,Pchar_Temp2,Pchar_Temp3:Pchar;FindEndOK:Boolean;
begin
//è? 1? ?? ?t ′? ?ú 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);
//è? 1? μú ò? ?? ×? ·? ?a '['IfBuffer='[?ˉ thenbegin//?ò 2é ?ò ']'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);
//?ú áD ±í ?D ?ó è? ×? ·? ′? Strings.Add(Pchar_Temp3);FreeMem(Pchar_Temp2);FreeMem(Pchar_Temp3);end;FreeMem(Pchar_Temp);end;FreeMem(Buffer);end;end;
end;
//?a ?? ′ú ?? ?¨ ò? á? ?ì ?÷ ?? ?¨ ?? ?ú μ? ?ü μ? ?? 3? μ? 1y 3ì
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
//è? 1? ?? ?t ′? ?ú ifFileExists(FFileName)thenbeginFindEndOK:=False;ExtIni_Start:=-1;ExtIni_End:=-1;
//?ì ?÷ è? ?? £? 2é ?ò SectionForExtIni_I:=0toFList.Count-1dobeginifUpperCase(FList.Strings[ExtIni_I])='['+UpperCase(Section)+']'thenbeginifExtIni_Start=-1thenExtIni_Start:=ExtIni_I;end;end;
//è? 1? 2é ?ò Section3é 1| 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);
//è? 1? μú ò? ?? ×? ·? ?a '['IfBuffer='['thenFindEndOK:=True;
//?ò ?a ?? ?μ ifFList.Strings[ExtIni_I]=''thenFindEndOK:=True;
//±ê ?? ?? ?? μ? ?á ê? DD ifFindEndOK=TruethenbeginifExtIni_End=-1thenbeginExtIni_End:=ExtIni_I;end;end;
//êí ·? ?ú ′? FreeMem(Buffer);end;end;ForExtIni_I:=ExtIni_Start+1toExtIni_End-1dobegin
//2é ?ò '='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;
//?a ?? ′ú ?? ?¨ ò? á? D′ è? ×? ·? ′? μ? 1y 3ì
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);
//è? 1? áD ±í °ü o? ?ú èY
if FList.Count > 0 then
begin
//?ì ?÷ è? ?? £? 2é ?ò 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;
//è? 1? 2é ?ò Section ê§ °ü
if ExtIni_Start = -1 then
begin
FList.Add('[' + Section + ']');
ExtIni_Start := FList.Count - 1;
end;
//è? 1? 2é ?ò Section 3é 1|
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);
//è? 1? μú ò? ?? ×? ·? ?a '['
if Buffer = '[' then FindEndOK := True;
//?ò ?a ?? ?μ
if FList.Strings[ExtIni_I] = '' then FindEndOK := True;
//±ê ?? ?? ?? μ? ?á ê? DD
if FindEndOK = True then
begin
if ExtIni_End = -1 then
begin
ExtIni_End := ExtIni_I;
end;
end;
//êí ·? ?ú ′?
FreeMem(Buffer);
end;
end;
//è? 1? ?? óD ?ò μ? ?? μ? ?á ê? DD
if ExtIni_End = -1 then
FList.Add(Ident + ' = ' + Value);
//è? 1? ?ò μ? ?? μ? ?á ê? DD
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);
//è? 1? ?ì ?÷ 3é 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.
[/code]
完成输入后,即完成了一个叫Extinifiles的非可视组件,安装到Delphi中,即可像操作inifiles一样操作Extinifiles,不仅操作方式兼容,生成的文件也相互兼容,不同之处是Extinifiles可以支持无限大的ini文件,可以使用到任何程序中。当然也可以将他改装并编译为一个Dll文件,便可以由VB调用了。在实际使用过程中,在赛阳300A的系统下可以非常快速的操作0M~1.5M的数据,而K6-2-300的系统则可以快速的操作0M~3M的数据。
以上组件在Delphi3+中文Windows98中调试通过,经实验证明同样兼容Delphi5。这个组件和演示程序亦可通过访问[url]http://qingyuan.csw.cnshare.net[/url]获得。(长沙 夏昆冈)
[/quote] *** 作者被禁止或删除 内容自动屏蔽 ***
页:
[1]