{*****************************************************************************} { } { Tnt Delphi Unicode Controls } { http://www.tntware.com/delphicontrols/unicode/ } { Extended TTntMemIniFile (compatible with all versions) } { } { Copyright (c) 1999-2007 Stanley Xu } { http://getgosurf.com/?go=supportFeedback&ln=en } { } {*****************************************************************************} {*****************************************************************************} { } { BACKGROUND: } { TTntMemIniFile buffers all changes to the INI file in memory. To write } { the data from memory back to the associated INI file, call the } { UpdateFile() method. However, the whole content of this INI file will } { be overwritten. Even those sections that are not used. This will make } { troubles, if two instances try to change the same file at the same } { time, without some method of managing access the instances may well end } { up overwriting each other's work. } { } { IDEA: } { TTntMemIniFileEx implementes a simple idea: To check the timestamp } { before each operation. If the file is modified, TTntMemIniFileEx will } { reload the file to keep the content updated. } { } { CONCLUSION: } { # TTntMemIniFileEx and TTntMemIniFile are ideal for read-only access. } { For instance: To read localization files, etc. } { # To perform mass WriteString() operations, please use the following } { code. } { BeginUpdate(); } { try } { for I := 0 to 10000 do } { WriteString(...); } { finally; } { EndUpdate(); } { UpdateFile; } { end; } { } {*****************************************************************************} unit TntIniFilesEx; {$INCLUDE TntCompilers.inc} interface uses TntClasses, TntIniFiles; type TTntMemIniFileEx = class(TTntMemIniFile) private FUpdateCount: Integer; FModified: Boolean; FLastAccessed: Integer; function FileRealLastAccessedTime: Integer; procedure GetLatestVersion; protected procedure LoadValues; // Extended public constructor Create(const FileName: WideString); override; procedure BeginUpdate; virtual; procedure EndUpdate; virtual; function ReadString(const Section, Ident, Default: WideString): WideString; override; procedure WriteString(const Section, Ident, Value: WideString); override; procedure ReadSection(const Section: WideString; Strings: TTntStrings); override; procedure ReadSections(Strings: TTntStrings); override; procedure ReadSectionValues(const Section: WideString; Strings: TTntStrings); override; procedure DeleteKey(const Section, Ident: WideString); override; procedure EraseSection(const Section: WideString); override; procedure UpdateFile; override; end; implementation uses SysUtils, TntSysUtils; { TTntMemIniFileEx } function TTntMemIniFileEx.FileRealLastAccessedTime: Integer; var H: Integer; // file handle begin Result := 0; H := WideFileOpen(FileName, fmOpenWrite); //fmOpenRead (?) if H <> -1 then try Result := FileGetDate(H); finally FileClose(H); end; end; procedure TTntMemIniFileEx.GetLatestVersion; begin if FLastAccessed = FileRealLastAccessedTime then Exit; LoadValues; // FLastAccess will be updated in LoadValues(...) end; procedure TTntMemIniFileEx.LoadValues; // Copied from TntIniFiles.pas var List: TTntStringList; begin if (FileName <> '') and WideFileExists(FileName) then begin List := TTntStringList.Create; try List.LoadFromFile(FileName); FLastAccessed := FileRealLastAccessedTime; // Extra FModified := False; // SetStrings(List); finally List.Free; end; end else Clear; end; constructor TTntMemIniFileEx.Create(const FileName: WideString); begin inherited Create(FileName); FUpdateCount := 0; end; procedure TTntMemIniFileEx.BeginUpdate; begin Inc(FUpdateCount); end; procedure TTntMemIniFileEx.EndUpdate; begin Dec(FUpdateCount); end; function TTntMemIniFileEx.ReadString(const Section, Ident, Default: WideString): WideString; begin GetLatestVersion; Result := inherited ReadString(Section, Ident, Default); end; procedure TTntMemIniFileEx.WriteString(const Section, Ident, Value: WideString); begin GetLatestVersion; inherited WriteString(Section, Ident, Value); FModified := True; UpdateFile; // Flush changes to disk end; procedure TTntMemIniFileEx.ReadSection(const Section: WideString; Strings: TTntStrings); begin GetLatestVersion; inherited ReadSection(Section, Strings); end; procedure TTntMemIniFileEx.ReadSections(Strings: TTntStrings); begin GetLatestVersion; inherited ReadSections(Strings); end; procedure TTntMemIniFileEx.ReadSectionValues(const Section: WideString; Strings: TTntStrings); begin GetLatestVersion; inherited ReadSectionValues(Section, Strings); end; procedure TTntMemIniFileEx.DeleteKey(const Section, Ident: WideString); begin GetLatestVersion; inherited DeleteKey(Section, Ident); FModified := True; UpdateFile; // Flush changes to disk end; procedure TTntMemIniFileEx.EraseSection(const Section: WideString); begin GetLatestVersion; inherited EraseSection(Section); FModified := True; UpdateFile; // Flush changes to disk end; procedure TTntMemIniFileEx.UpdateFile; begin if not FModified or (FUpdateCount > 0) then Exit; inherited; end; end.