Zitat von
Cosamia:
Delphi-Quellcode:
begin
if FindFirst(dir+'*',faAnyFile,search)=0 then
begin
An dieser Stelle würde ich an deiner Stelle schon mit einem Schutzblock anfangen. Dieser stellt dann sicher, dass FindClose auf jeden Fall aufgerufen wird.
Zitat von
Cosamia:
Delphi-Quellcode:
if (((search.Attr and faDirectory)>0) and (not(leftStr(search.Name,1)='.'))) then getFiles(dir+search.Name+'\')
else
Sorry, aber ganz schlecht! Einerseits würde ich hier völlig überlesen, was dort im Falle des if's passiert. Viel Besser ist es, wenn Du für jede Struktur immer ein begin-end-Block verwendest. Der ist natürlich nicht nötig für die korrekte Semantik, erleichtert aber die Lesbarkeit immens und senkt eventuelle Folgefehler beim einfügen weiterer Anweisungen.
Besser wäre hier also
Delphi-Quellcode:
if (((search.Attr and faDirectory)>0) and (not(leftStr(search.Name,1)='.'))) then
begin
getFiles(dir+search.Name+'\')
end // if (((search.Attr and faDirectory)>0) and (not(leftStr(search.Name,1)='.')))
else
So ist viel deutlicher, dass es sich hier um zwei verschiedene Fälle handelt und was wann getan wird. Das andere, was mich hier stören würde, ist die Rekursion. Natürlich ist es nicht falsch oder so, aber bei einer hohen Verschachtelungstiefe hast Du ein Problem, die Ressourcen. Jedes FindFirst belegt ein
Handle, dass an anderer Stelle fehlt. Du gehst hier erst in die Tiefe eines Ordners, bevor Du das
Handle des aktuellen Ordners wieder frei gibst. Wie gesagt, tief genug und es gibt Probleme (vorallem wird das System langsam!). Besser wäre es, wenn Du Dir hier nur die Ordner merkst, die Du als nächstes besuchen möchtest. Hier würde ich Dir (wieder) zu einer TStringList raten. Leg einfach eine an, füge mit add den Pfad der neuen Ordner hinzu und mach erstmal mit dem Rest weiter. Natürlich kannst Du so auch die Dateien in eine eigene Liste schreiben. Damit hast Du dann erstmal die Suche für einen Ordner abgeschlossen und die zu untersuchenden Dateien und Ordner in je einem Puffer stehen. Nun kannst Du schon FindClose aufrufen (und damit erstmal nicht benötigte Ressourcen frei geben).
Dann kannst Du selbst entscheiden, wie Du weitermachst (erst Ordner oder Dateien).
Statt dem dir+search.Name+'\' solltest Du lieber die Funktion IncludeTrailingPathDelimiter verwenden. Diese stellt sicher, dass das korrekte Pfad Trennzeichen angefügt wird, wenn es noch nicht vorhanden ist.
Ja, hast Du nun die zwei Listen, nenen wir sie Dateien und Ordner, dann würde ich Dir empfehlen diese nun in je einer eigenen Routine weiter zu verarbeiten. Auch hier geht es nur um die bessere Lesbarkeit. Je mehr kleine Routinen Du verwendest, desto leichter kannst Du überblicken, was eine solche Routine macht. Das senkt die Anzahl der Fehler und erhöht die Lesbarkeit (und ggf. natürlich auch die Wiederverwendbarkeit).
Bei den Ordnern ist die Vorgehensweise klar, Du kannst einfach die Methode getFiles für jeden gespeicherten Pfad aufrufen. Bleiben also noch die Dateien. Hier kannst Du wie bereits gesagt jede Datei einfach mit einer TStringList laden (LoadFromFile).
Wenn Du die Zeile kennst, auf die Du zugreifen möchtest, dann kannst Du dem schon geposteten Beispiel entnehmen, wie Du diese Zeile extrahierst.
Hier ist es nur noch wichtig, welches Datum gespeichert wurde und ob dieses gültig ist. Dazu steht Dir die Funktion TryStrToDate zur Verfügung. Diese probiert die Umwandlung eines Strings in ein Datum aus und gibt zurück, ob dies möglich war oder nicht.
Die Umwandlung hängt allerdings immer vom verwendeten Datumsformat ab. Dies kann mit jeder Windowsversion und natürlich eingestellter Lokalisierung variieren (z.B. je nach Land). Da Du ein bestimmtes Format erwartest, solltest Du dies auch zurück geben. Dazu kannst Du einfach mit der Funktion getLocaleFormatSettings die lokalen Einstellungen als TFormatSettings-Record zurückgeben lassen.
In diesen FormatSettings änderst Du dann ShortDateFormat auf 'dd.mm.YYYY' und übergibst diese veränderten LocalSettings dann mit an die TryStrToDate-Funktion. Bekommst Du dann ein False zurück, kannst Du das aktuelle Datum mit FormatDate als String erzeugen und für diesen String in die TStringList einfügen. Dann einfach wieder speichern und fertig.