Einzelnen Beitrag anzeigen

Der schöne Günther

Registriert seit: 6. Mär 2013
6.111 Beiträge
 
Delphi 10 Seattle Enterprise
 
#15

AW: Wie gehe ich mit meinen temporären Daten um?

  Alt 4. Sep 2015, 09:38
Danke für die vielen Antworten bisher!

Ich will es an dieser einen Anwendung gar nicht zu sehr festmachen. Dem Anwender kann ich (im negativen Sinne) alles zutrauen. Auch dass er 500 mal den PDF-Betrachter offen lässt und wieder ins Hauptprogramm wechselt.

Ich hätte gedacht dass Windows mit der Zeit automatisch das macht, wenn ich im Explorer auf Bereinigen gehe. Da es da wohl nichts gibt muss man periodisch wohl alles rauswerfen. Ich dachte dann an so etwas in der Art. Würdet ihr das so absegnen oder übersehen ich noch etwas?

Delphi-Quellcode:
unit App.TempFileManager;

interface uses System.TimeSpan, System.Classes, System.Types;

type
   TTempFileManager = class(TObject)
      protected const
         guid = '{255AC97A-A42E-44F3-86E1-DF00B7C67FD5}';
      protected var
         maxFileAge: TTimeSpan;
      protected
         function getPath(): String;
         function findFiles(const olderThan: TDateTime): TStringDynArray;
      public var
         cleanupOnEveryRequest: Boolean;
      public
         constructor Create(const maxFileAge: TTimeSpan); overload;
         constructor Create(const maxFileAgeHours: Integer); overload;

         procedure doCleanup(const recursive: Boolean = False);
         /// <summary>
         /// Liefert einen neuen Dateinamen im <see cref="Path" />-Verzeichnis
         /// </summary>
         /// <param name="extension">
         ///      Optionale Dateinamenerweiterung. Beispiel: <c>.pdf</c> oder
         /// <c>txt</c>. Das Trennzeichen-Prefix ist optional
         /// </param>
         function getTempFileName(const extension: String = ''): String;
         /// <summary>
         /// Liefert einen <c>TFileStream</c> auf eine neue, im
         /// <see cref="Path"/>-Verzeichnis erstellte Datei
         /// </summary>
         /// <param name="extension">
         ///      Optionale Dateinamenerweiterung. Beispiel: <c>.pdf</c> oder
         /// <c>txt</c>. Das Trennzeichen-Prefix ist optional
         /// </param>
         function getTempFile(const extension: String = ''): TFileStream;
      public //properties
         property Path: String read getPath;
   end;

implementation uses System.IoUtils, System.SysUtils, System.DateUtils;

type
   TDateTimeHelper = record helper for TDateTime
      function IncSpan(const timeSpan: TTimeSpan): TDateTime;
      function DecSpan(const timeSpan: TTimeSpan): TDateTime;
   end;

   TFileHelper = record helper for TFile
      class procedure TryDelete(const Path: String); static;
   end;

{ TTempFileManager }

constructor TTempFileManager.Create(const maxFileAgeHours: Integer);
var
   asTimeSpan: TTimeSpan;
begin
   asTimeSpan := TTimeSpan.FromHours(maxFileAgeHours);
   self.Create(asTimeSpan);
end;

constructor TTempFileManager.Create(const maxFileAge: TTimeSpan);
begin
   inherited Create();
   self.maxFileAge := maxFileAge;
end;

procedure TTempFileManager.doCleanup(const recursive: Boolean = False);
var
   mustBeOlderThan:   TDateTime;
   foundFiles:         TStringDynArray;
   filePath:         String;
begin
   mustBeOlderThan := Now().DecSpan(maxFileAge);
   foundFiles := findFiles(mustBeOlderThan);

   for filePath in foundFiles do TFile.TryDelete(filePath);
end;

function TTempFileManager.findFiles(const olderThan: TDatetime): TStringDynArray;
var
   predicate: TDirectory.TFilterPredicate;
begin
   if not TDirectory.Exists(Path) then Exit(nil);

   predicate :=
      function(const Path: string; const SearchRec: TSearchRec): Boolean
      begin
         // SearchRec.TimeStamp bezeichnet das "Geändert am"
         Result := CompareDateTime(SearchRec.TimeStamp, olderThan) = LessThanValue;
      end;

   Result := TDirectory.GetFiles(Path, TSearchOption.soTopDirectoryOnly, predicate);
end;

function TTempFileManager.getTempFileName(const extension: String): String;
var
   filename: TFileName;
begin
   if cleanupOnEveryRequest then doCleanup();

   filename := TPath.GetGUIDFileName();
   if not extension.IsEmpty() then begin
      if not extension.StartsWith(TPath.ExtensionSeparatorChar) then
         filename := filename + TPath.ExtensionSeparatorChar;
      filename := filename + extension;
   end;

   Result := TPath.Combine(Path, filename)
end;

function TTempFileManager.getPath(): String;
begin
   Result := TPath.GetTempPath();
   Result := TPath.Combine(Result, guid);
end;

function TTempFileManager.getTempFile(const extension: String): TFileStream;
var
   path: String;
begin
   path := getTempFileName(extension);
   if TFile.Exists(path) then TFile.Delete(path);
   Result := TFile.Create(path);
end;

{ TDateTimeHelper }

function TDateTimeHelper.IncSpan(const timeSpan: TTimeSpan): TDateTime;
begin
   Result := System.DateUtils.IncMilliSecond(self, Round(timeSpan.TotalMilliseconds));
end;

function TDateTimeHelper.DecSpan(const timeSpan: TTimeSpan): TDateTime;
begin
   Result := System.DateUtils.IncMilliSecond(self, Round(-timeSpan.TotalMilliseconds));
end;

{ TFileHelper }

class procedure TFileHelper.TryDelete(const Path: String);
begin
   try
      Delete(Path);
   except
      on EDirectoryNotFoundException do;
      on EFileNotFoundException do;
      on EInOutError do;
   end;
end;

end.
  Mit Zitat antworten Zitat