Einzelnen Beitrag anzeigen

nahpets
(Gast)

n/a Beiträge
 
#35

AW: Ini-Inhalt geht in sehr seltenen Fällen verloren (TMemIniFile)

  Alt 11. Jan 2016, 14:40
Hab' mal so zum Spass 'nen INI-Historienkrimskram zusammengedaddelt:
Delphi-Quellcode:
const
  ciMaxKopieen = 10; // Anzahl der maximal anzulegenden Sicherungskopieen.
  ciMindestIniGroesse = 21; // Die Ini-Datei muss eine Mindestgröße haben,
                            // unterhalb dieser Größe fehlen auf jeden Fall
                            // irgendwelche Einträge...
                            // Sei der Mindestinhalt der INI-Datei
                            // [Section]
                            // Ident=
                            // so muss ihre Größe mindestens 21 Byte sein.

function GetFileSize(const sFile: String): Int64;
var
  fFile : THandle;
  wfd : TWIN32FINDDATA;
begin
  Result := 0;
  if not SysUtils.FileExists(sFile) then exit;
  fFile := Windows.FindFirstfile(pchar(sFile),wfd);
  if fFile = INVALID_HANDLE_VALUE then exit;
  Result := (wfd.nFileSizeHigh * (MAXDWORD)) + wfd.nFileSizeLow;
  Windows.FindClose(fFile);
  // Hier könnte man jetzt noch weitere Plausibilitätsprüfungen für
  // die INI-Datei machen...
end;

procedure Irgendwas;
var
          i : Integer;
          ini : TMemIniFile;
          sIniFile : String;
          sBakFileA : String;
          sBakFileB : String;
begin
  // Beim Programmstart:
  // Den Namen der INI-Datei festlegen.
  sIniFile := ChangeFileExt(Application.ExeName,'.ini');
  // Fehlt diese Datei oder ist ihre Größe kleiner der Mindestdateigröße?
  if not FileExists(sIniFile) or (GetFileSize(sIniFile) < ciMindestIniGroesse) then begin
    // Prüfen, ob wir eine der letzten 10 Sicherungskopien finden...
    for i := 1 to ciMaxKopieen do begin
      // Name der Sicherungskopie i erstellen.
      sBakFileA := Format('%s.%.3d',[sIniFile,i]);
      // Gibt es sie und ist sie größer/gleich der Mindestdateigröße?
      if FileExists(sBakFileA) and (GetFileSize(sBakFileA) >= ciMindestIniGroesse) then begin
        // Sicherungskopie umbennen auf den eigentlich gewünschten Dateinamen.
        RenameFile(sBakFileA,sIniFile);
        // Schleife verlassen.
        break;
      end;
    end;
  end;
  // Ini-Datei laden...
  ini := TMemIniFile.Create(sIniFile);

  // ... Weitere Programmlogik ...
  ini.WriteString('Section','Ident',sBakFileA);
  // ...

  // Beim Programmende:
  // (eventuell) vorhandene Sicherungskopieen löschen bzw. umbennen,
  // so dass wir immer eine Historie von maximal ciMaxKopieen Ini-Dateien haben.
  for i := ciMaxKopieen downto 2 do begin
    // Name der Sicherungskopie i und i - 1 erstellen.
    sBakFileA := Format('%s.%.3d',[sIniFile,i]);
    sBakFileB := Format('%s.%.3d',[sIniFile,i - 1]);
    // Sicherungskopie mit der höheren Nr. in der Endung löschen.
    DeleteFile(sBakFileA);
    // vorhergehende Sicherungskopie umbenennen.
    RenameFile(sBakFileB,sBakFileA);
  end;
  // Dateinamen für die erste Sicherungskopie erstellen
  sBakFileA := Format('%s.%.3d',[sIniFile,1]);
  // und die letzte INI-Datei in die erste Sicherungskopie umbenennen.
  RenameFile(sIniFile,sBakFileA);
  // Ini-Datei speichern.
  ini.UpdateFile;
  // und Schluss ist.
  ini.Free;
end;
Sinnvollerweise baut man sich 'nen Nachfolger von TMemIniFile und gibt diesem Nachfolger statt der Konstanten entsprechende Attribute.

Den "Kram" vom Programmstart übernehme man in das überschriebene Create, den "Kram" zum Programmende ins überschriebene Destroy oder zusammen mit UpdateFile in eine eigene Routine, die man auch separat zu wichtigen Zeitpunkten aufrufen kann und zusätzlich im Destroy aufruft.
  Mit Zitat antworten Zitat