Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Rekursives durchsuchen und Letzten Dateizugriff auslesen (https://www.delphipraxis.net/150387-rekursives-durchsuchen-und-letzten-dateizugriff-auslesen.html)

DeddyH 16. Apr 2010 13:49

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Zeig doch einmal die ganze aufrufende Methode, nicht nur Häppchen davon.

hoika 16. Apr 2010 13:53

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Hallo,

Breakpoint auf

List.Add(Directory+SR.Name+'#'+IntToStr(SR.FindDat a.nFileSizeHigh)+'*'
+IntToStr(SR.FindData.ftLastAccessTime.dwLowDateTi me));

und Laufenlassen.


Hast du mal c:\test wie im Bsp. von DeddyH angelegt
und ein paar Dateien reingepackt.

Du verschweigst uns den Code, der nach dem Aufruf kommt,

Vielleicht steht dort ja auch ein List.Clear ;)



Heiko

DeddyH 16. Apr 2010 14:00

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Ich hab die Klassenmethode jetzt mal auf das Notwendigste gekürzt, auch wenn das vermutlich nicht fehlerverursachend war:
Delphi-Quellcode:
class procedure TDataWork.GetAllFilesInDirectorys(Directory: string; List: TStrings; ClearList: Boolean);

    procedure ScanDir(const Directory: string);
    var SR  : TSearchRec;
    begin
      if FindFirst(Directory+'*.*',faAnyFile,SR) = 0 then
      begin
        try
          repeat
            if (SR.Attr and faDirectory) = faDirectory then
            begin
              if (SR.Name <> '.') and (SR.Name <> '..') then
                ScanDir(IncludeTrailingPathDelimiter(Directory+SR.Name));
            end
            else
            begin
              List.Add(Directory+SR.Name+'#'+IntToStr(SR.FindData.nFileSizeHigh)+'*'
                     +IntToStr(SR.FindData.ftLastAccessTime.dwLowDateTime));
            end;
          until FindNext(SR) <> 0;
        finally
          FindClose(SR);
        end;
      end;
    end;

begin
  List.BeginUpdate;
  try
    if ClearList then
    begin
      List.Clear;
    end;
    Directory := trim(Directory);
    if Directory = '' then
    begin
      Exit;
    end;
    Directory := IncludeTrailingPathDelimiter(Directory);
    ScanDir(Directory);
  finally
    List.EndUpdate;
  end;
end;

AnyKey 16. Apr 2010 14:02

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Der Code ist ziemlich lang, hab noch mal drüber geguckt und es ist kein List.Clear drin ^^ aber was ich rausgefunden habe ist, dass er nicht einmal was in die Liste schreibt, so wie ich es die ganze Zeit schon vermutet habe.

Delphi-Quellcode:
var LastAccess : Array of string;
var List      : TStringList;
var Path      : string;
var i         : Integer;
begin
  List := TStringList.Create;
  Main.UniConnection1.Connect;
  if Main.UniConnection1.Connected = True then
  begin
    Main.UniQuery1.SQL.Clear;
    Main.UniQuery1.SQL.Add('SELECT Pfad FROM tblPfad;');
    Main.UniQuery1.Execute;
    Path := Main.UniQuery1.Fields[0].Value;
  end;
  TDataWork.GetAllFilesInDirectorys(Path,List,true);
  setLength(LastAccess,List.Count-1);
  for i := 0 to List.Count-1 do
  begin
    LastAccess[i] := TDataWork.GetLastAccesstime(List.Strings[i]);
  end;
  FreeAndNil(List);
Hab mich mal aufs wesentliche beschränkt.

DeddyH 16. Apr 2010 14:15

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Wie ist es so?
Delphi-Quellcode:
var LastAccess : Array of string;
    List      : TStringList;
    Path      : string;
    i         : Integer;
begin
  Path := '';
  try
    fMain.UniConnection1.Connect;
  except
    MessageBox(0,'Datenbankverbindung fehlgeschlagen!','Fehler',MB_ICONWARNING);
  end;
  if fMain.UniConnection1.Connected{ = True} then
  begin
    fMain.UniQuery1.SQL.Text := 'SELECT Pfad FROM tblPfad';
    fMain.UniQuery1.{Execute;}Open;
    Path := fMain.UniQuery1.Fields[0].Value;
    fMain.UniQuery1.Close;
  end;
  if Path <> '' then
    begin
      List := TStringList.Create;
      try
        TDataWork.GetAllFilesInDirectorys(Path,List,true);
        setLength(LastAccess,List.Count{-1});
        for i := 0 to List.Count-1 do
        begin
          LastAccess[i] := TDataWork.GetLastAccesstime(List{.Strings}[i]);
        end;
      finally
        FreeAndNil(List);
      end;
    end;

AnyKey 16. Apr 2010 14:26

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Ich begreifs einfach nicht, selbst wenn ich den Pfad fest in den Code schreibe funktioniert es nicht. die Liste bleibt leer und ich bekomme bei dem Aufruf von List.Count einen Fehler.

Ich bin am verzweifeln...

Danke noch mal für eure Hilfe!!

Ich hoff mal ich bekomm das mit eurer Hilfe hin!

Edit: Ich hab jetzt mal spasseshalber ein Memo drauf gelegt und dem List zugewiesen, ratet mal was passiert....... es bleibt leer

Gruß
AnyKey

DeddyH 16. Apr 2010 14:29

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Zitat:

Zitat von AnyKey
ich bekomme bei dem Aufruf von List.Count einen Fehler.

Das ist in der Tat bemerkenswert. Jetzt nimmst Du Dir mal die komplette Routine (ungekürzt), packst sie in eine Textdatei und hängst sie hier an, vielleicht sieht man dann, was da schiefgeht.

hoika 16. Apr 2010 14:34

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Hallo,

Zitat:

die Liste bleibt leer und ich bekomme bei dem Aufruf von List.Count einen Fehler
Ist ja interessant, dass du das jetzt erst sagst ... ;)
Ist die Fehlermeldung geheim oder warum sagst du sie uns nicht ?

Steht die vielleicht irgendwo ein List.Free ?;


*auf die Textdatei wart*


Heiko

AnyKey 16. Apr 2010 14:37

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Der Fehler sagt lediglich 'Fehler bei Bereichsprüfung' und er kommt sobald ich dem Array List.Count-1 zuweisen will, was ja nicht gehen kann, da List.Count = 0 ist, obwohl es das ja nicht sein dürfte wenn ich die liste gefüllt habe...

Edit: wie schon gesagt, die Proceduren liegen in zwei verschiedenen Units, die GetAllFilesInDirectory in einer Klasse und der Button zum auslösen in einem Fromular.

DeddyH 16. Apr 2010 14:42

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Wieso die Liste leer bleibt, hab ich nicht erkennen können, aber das SetLength ist so auf jeden Fall falsch. Wieso List.Count - 1 und nicht List.Count?

AnyKey 16. Apr 2010 14:44

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Weil ein Array doch immer mit 0 beginnt oder nicht? Naja ist ja egal, hab jetzt mal das -1 weggelassen, jetzt funktioniert wenigstens meine Anwendung wieder, aber die Liste ist sicherlich immer noch leer...

DeddyH 16. Apr 2010 14:46

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Das Array beginnt bei 0, die Liste auch. Übrigens bekommst Du ein Speicherleck, wenn die DB-Verbindung fehlschlägt, da die Liste dann nicht wieder freigegeben wird.

hoika 16. Apr 2010 14:47

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Hallo,

der Code sieht OK aus.

Ausser
LastAccess: array of String

Warum die Leute sowas statt einer StringList nehmen, ist mir ein Rätsel.


Die Frage ist, welchen Wert hat Pfad.


Heiko

AnyKey 16. Apr 2010 14:51

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Danke, werd ich ändern, hatte ich nicht drüber nachgedacht.
Also es funktioniert immer noch nicht, hab noch mal einen Breakpoint an der stelle in der Funktion gesetzt in der ich die Liste befülle, aber da springt er nie rein, keine ahnung warum nicht. Dumme Frage: Daran das die proceduren sich in zwei verschiedenen Units befinden und ich die StringList in die Klasse in der Procedure als List: TStrings übergeb kanns nicht liegen oder?

Pfad hat wenn ich debugge in der Aufrufenden und in der GetFilesinDirectory Procedure einen Wert wie: 'C:\Dokumente und Einstellungen\Eigene Dateien\Beispiele'

Ich hab echt keinen plan mehr :(

Gruß
AnyKey

DeddyH 16. Apr 2010 14:55

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Solange die Unit mit der Klasse eingebunden ist, kann ja nix schiefgehen (sonst müsste der Compiler aber auch meckern).

[edit] Kann es sein, dass da ein "end;" zuviel ist? Ich hab die Datei in PSPad offen und kann da eins nicht so recht zuordnen. Versuch es mal mit diesen Änderungen (else-Zweige hab ich jetzt einmal weggelassen):
Delphi-Quellcode:
procedure TfMDIChild.FormCreate(Sender: TObject);
var LastAccess : Array of string;
    Benutzer  : string;
    List      : TStringList;
    Pfad      : string;
    i         : Integer;
begin
  Pfad := '';
  Benutzer := TWindowsFunctions.GetUser;
  // 1. Datenbankverbindung herstellen, bwz. DB erstellen falls noch nicht existiert
  try
    fMain.UniConnection1.Connect;
  except
    MessageBox(0,'Datenbankverbindung fehlgeschlagen!','Fehler',MB_ICONWARNING);
  end;
  // 2. Wenn TypeFlag = Archiv dann Child mit VirtualExplorerTreeView erstellen
  if fMain.TypeFlag = rsArchiv then
  begin
    if fMain.UniConnection1.Connected then
    begin
      fMain.UniQuery1.SQL.Text := 'SELECT QZPfad FROM tblQuelleZiel WHERE QZQuelle = 1 AND QZBenutzer = :benutzer';
      fMain.UniQuery1.ParamByName('benutzer').Value := Benutzer;
      fMain.UniQuery1.Execute;
      Pfad := fMain.UniQuery1.FieldByName('QZPfad').Value;
    end;
    VET := TVirtualExplorerTreeview.Create(Self);
    VET.Name := 'VET';
    VET.Parent := Self;
    VET.Active := True;
    VET.Align := alClient;
    VET.CheckImageKind := ckDarkCheck;
    VET.RootFolder := rfCustom;
    VET.RootFolderCustomPath := Pfad;
    VET.TreeOptions.MiscOptions := [toAcceptOLEDrop, toCheckSupport, toEditable,
                                    toToggleOnDblClick];
    VET.OnInitNode := VETInitNode;
//    end;
  // 3. Archivierungsprüfung!!
    if Pfad <> '' then
    begin
      List := TStringList.Create;
      try
        TDataWork.GetAllFilesInDirectorys(Pfad,List,true);
    // 4. LastAccessTime prüfen:
        setLength(LastAccess,List.Count);
        for i := 0 to List.Count-1 do
        begin
          LastAccess[i] := TDataWork.GetLastAccesstime(List.Strings[i]);
        end;
      finally
        FreeAndNil(List);
      end;
    end;
  // 5. Daten in die Datenbank schreiben
    if fMain.UniConnection1.Connected then
    begin

    end;
  // 6. die archivierbaren Ordner im VirtualTreeView markieren:
  // hierfür InitNode aufrufen dort wird das dann gemacht, dort muss
  // dann auch die Prüfung auf die DB gemacht werden, ob archivierbar oder nicht
  end;
end;
[/edit]

hoika 16. Apr 2010 15:02

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Hallo,

Delphi-Quellcode:
if FindFirst(Directory+Mask,faAnyFile and not faDirectory, SR) = 0 then
Woher hast du denn das and not ??
Das wird per or zusammengefasst

Nimm das mal komplette raus und rpprüfe in der repeat until,
ob die jeweiliges "Datei" ein Verzeichnis ist.

Delphi-Quellcode:
if if (SR.Attr and faDirectory) = faDirectory then
begin
  List.Add(XXX)
end;

Heiko

DeddyH 16. Apr 2010 15:04

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Das hatte ich in #43 schon :mrgreen:

[edit] and not entfernt ein bestimmtes Bit, das ist schon richtig ;) [/edit]

p80286 16. Apr 2010 15:24

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Ich hab mal ein wenig gespielt.
Hoikas Frage nach dem Pfad war wohl richtig, da wenn der Pfad nicht vorhanden ist, ist auch die Liste leer!

Delphi-Quellcode:
if DirectoryExists(path) then
  GetAllFilesInDirectorys(path, ll,true)
else
  showmessage('falsche Pfadangabe:'+path);
was habt Ihr gegen
Delphi-Quellcode:
and not faDirectory
ist das nicht das gleiche wir fahidden or fasystem or faarchive.....(ohne faDirectory)
oder eben faAnyfile mit not(faDirectory) maskiert.
oder hab ich da was falsch in Erinnerung?

Gruß
K-H

Edith:
Tippfehler

DeddyH 16. Apr 2010 15:27

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Wer hat denn etwas gegen das and not? Mich persönlich hat nur gestört, dass alles 2 mal abgeklappert wird, was man auch mit einem Mal erledigen kann. Und angeblich funktioniert der Code ja mit einer Listbox, mit einer Stringliste aber nicht (was ich mir allerdings nicht so richtig vorstellen kann).

p80286 16. Apr 2010 15:36

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Das liegt am übergebenen Pfad!
Gruß
K-H

hoika 16. Apr 2010 15:44

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Hallo,

Zitat:

Das hatte ich in #43 schon Mr. Green
So langsam verliere ich den Überblick ;)

An den TE.
Mache mal ein neues komplettes Bsp.-Projekt,
was genau (UND NUR GENAU) den Fehler reproduziert.
Also nichts mit Pie und DB.

Als Pfad ExtractFilePath(Application.ExeName)+'\'; (das ist das Verzeichnis der Exe selber).

Das Projekt zippen und ohne Exe anhängen.


Das ist hier nur rumgestochere.

Update:
Und verballert unsere schöne kostbare Zeit.



Heiko

DeddyH 16. Apr 2010 15:56

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Seh ich genauso. Einfach mal einen Button nehmen, den Pfad exakt so übergeben, wie er in der DB steht und das Ganze mal in eine sichtbare Liste, sonst kommen wir nicht weiter.

shmia 16. Apr 2010 16:35

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Liste der Anhänge anzeigen (Anzahl: 2)
Also wenn man alles richtig machen möchte, dann sollte man Events als Technik zur Rückgabe der Dateiinformationen einsetzen.
Eine normale StringList ist zu begrenzt, da man im Prinzip nur den Dateinamen bekommt und andere Informationen (Dateigrösse, Flags,...) unter den Tisch fallen.

Zunächst benötigt man einen Record zur Rückgabe der Daten:
Delphi-Quellcode:
TFileInformation = record
  Name : string;
  Path : string;
  IsDir : boolean;
  ReadOnlyFlag, HiddenFlag, SystemFlag : boolean;
  Owner : TOwner;
  Size : Int64;
  ...
end;
Bei jedem gefundenen File oder Directory werden die Infos von TSearchRec auf den "benutzerfreundlichen" Record TFileInformation kopiert und dann ein Event ausgelöst.
"Benutzerfreundlich" heisst hier, dass die Daten im Record TFileInformation so aufbereitet sind, dass man sie bequem und ohne Klimmzüge abgreifen kann.

Das Event sieht so aus:
Delphi-Quellcode:
TFileFindEvent = procedure(Sender:TObject; const FileInformation:TFileInformation) of object;
Im Anhang gibt es ein Demoprojekt in dem das Konzept umgesetzt wird.
Bestimmte Dateiattribute (ReadOnlyFlag, Owner, Size nur 32-bit genau) werden z.Zt. noch nicht ausgewertet aber das lässt sich ja leicht nachholen.
Wenn jemand meinen Sourcecode benutzen möchte, dann erwarte ich als Gegenleistung dass das verbessert und auf der DP gepostet wird.

PS: leicht verbesserte Version hochgeladen

DeddyH 16. Apr 2010 16:39

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Ehrlich gesagt verstehe ich nicht ganz, wozu der Event dienen soll (außer das Programm zu verlangsamen, wenn eine Ereignisroutine hinterlegt ist :mrgreen:). Ich für meinen Teil würde dann doch eher aus dem Record eine Klasse machen und diese dann per AddObject in die Stringliste schieben. Oder hab ich Dich nicht richtig verstanden?

shmia 16. Apr 2010 16:55

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Zitat:

Zitat von DeddyH
Ehrlich gesagt verstehe ich nicht ganz, wozu der Event dienen soll (außer das Programm zu verlangsamen, wenn eine Ereignisroutine hinterlegt ist :mrgreen:).

Durch das Event lässt sich die Klasse TFileScanner an jedes Problem anpassen.
Man kann die Dateinamen in eine Stringliste kopieren oder man schreibt die Dateiinformationen unmittelbar und ohne Zwischenspeicher in eine Datenbank oder man schreibt sie in eine XML-Datei, usw.
Zusätzlich besteht so auch die Möglichkeit, den Vorgang vorzeitig abzubrechen (Methode Stop).

Der Aufruf eines Event pro Datei ist der (geringe) Preis den man für die universelle Einsetzbarkeit bezahlen muss.
Zitat:

Zitat von DeddyH
Ich für meinen Teil würde dann doch eher aus dem Record eine Klasse machen

Hab' ich mir auch überlegt, bin dann aber zum Schluss gekommen dass ein Record im Moment ausreichend ist, weil ja nur Daten aber keine Methoden vorhanden sind.
Wäre aber trotzdem noch eine Überlegung wert.

DeddyH 16. Apr 2010 18:14

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Ach, so war das gemeint, keine schlechte Idee. Wenn man das dann noch mit der angesprochenen Klasse verbindet, die den TSearchRec entgegennimmt und die Felder den Anforderungen entsprechend parst, wäre das glatt die Luxus-Variante :zwinker:

AnyKey 17. Apr 2010 09:13

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Hi,

sorry das ich mich erst jetzt wieder melde! Also ich hab die Testanwendung die ich am Anfang mal geschrieben hatte wieder rausgekramt, in der hatte ich die Funktion bevor ich sie in meine Anwendung übernommen hatte getestet, ob sie überhaupt funktioniert. Und was ist, selbst da funktioniert es nicht mehr :(
Das kann doch echt nicht wahr sein, ich meine ich weiß hundert %ig das es funktioniert hat, sonst hätte ich die Funktion ja nicht eingebaut und jetzt funktioniert garnichts mehr :( ich habe in der Testanwendung auch mal einen Breakpoint an der Stelle gesetzt, wo die Liste befüllt werden soll, er geht einfach nicht an diese Stelle, im Code von DeddyH das selbe spiel...

Ich weiß nicht mehr weiter ich habe nur eine ListBox versucht zu befüllen.

Gruß
AnyKey

DeddyH 17. Apr 2010 09:27

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Und Du bist ganz sicher, dass das Verzeichnis auch existiert?

[edit] Versuch mal das Programm im Anhang und gib Bescheid, ob es funktioniert. [/edit]

AnyKey 17. Apr 2010 10:15

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Hi,

Danke für eure Hilfe, es funktioniert jetzt, vielleicht waren die Ordner mit denen ich getestet habe wirklich leer, aber ich habe mit mehreren Ordnern getestet und es ging nicht, war vielleicht doch irgendwo ein fehler bei mir im Code. Naja egal was es jetzt auch war ich Danke euch noch mal für eure Hilfe und die Zeit die ich euch geklaut habe. Selbst wenn es jetzt doch an den Ordnern lag habt ihr mir jetzt noch ein Paar elegantere Lösungen aufgezeigt, die ich dann auch umsetzen werde. ;)

Ein Paar fragen habe ich allerdings noch:
1. In was für einer größe wird die Filesize angegeben? => damit ich weiß wie/ob ich umrechnen muss.
2. Wie ist die Datetime aufzuschlüsseln? da steht z.B. sowas wie 30067129 was davon brauche ich als Datum und was ist für mich irrelevant? Müsste das Datum dann noch anpassen, denn das andere Datum mit dem ich es vergleichen will, bekomme ich mit Punkten im Fromat TT.MM.JJJJ übergeben.

Gruß
AnyKey

DeddyH 17. Apr 2010 10:20

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Du hast die verlinkte Hilfe nicht wirklich gelesen, da steht alles drin.

AnyKey 17. Apr 2010 10:26

Re: Rekursives durchsuchen und Letzten Dateizugriff auslesen
 
Doch gelesen hab ich sie, die Hilfe ist ja auch in Delphi vorhanden, aus zeitmangel hab ich sie leider nicht genau gelesen :oops:
Aber gut wenn da alles drin steht guck ich da noch mal genauer rein.

Danke für eure Hilfe!

Gruß
AnyKey


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:28 Uhr.
Seite 2 von 2     12   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz