Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Fortschrittsanzeige beim Durchsuchen der Festplatte (https://www.delphipraxis.net/76285-fortschrittsanzeige-beim-durchsuchen-der-festplatte.html)

newuser01 1. Sep 2006 11:39


Fortschrittsanzeige beim Durchsuchen der Festplatte
 
Hallo ich bins mal wieder :) Ich habe diesmal folgendes Problem. Ich möchte wärend die Festplatte nach bestimmten mp3 Dateien durchsucht wird diesen Vorgang auch anzeigen lassen (Progressbar)den Code wie ich nach den Dateien suche habe ich siehe unten. Nun muss das ganze nur noch Zeitgleich mit der Progressbar zusammenarbeiten um den Fortschritt anzuzeigen. Dazu brauche ich ja den Max-Wert der Progressbar den könnte ich ja übergeben in dem ich die ganze Festplatte ersteinmal nach allen mp3 Dateien durchsuchen lasse und dieses dann in eine Stringlist schreibe um dann Count der Stringlist der Progressbar zu übergeben. Danach brauch ich ja dann nur noch über eine Schleife der Progressbar.Position i übergeben soweit meine Idee nur bekomm ich das nicht ganz hin :(

//hier der Code um bestimmte mp3 Dateien zu suchen

Delphi-Quellcode:

procedure GetFilesInDirectory(ADirectory: string; AMask: String; AList: TStrings; ARekursiv: Boolean);
var
  SR: TSearchRec;
begin
  if (ADirectory<>'') and (ADirectory[length(ADirectory)]<>'\') then
    ADirectory:=ADirectory+'\';

  if (FindFirst(ADirectory+AMask,faAnyFile-faDirectory,SR)=0) then begin
    repeat
      if (SR.Name<>'.') and (SR.Name<>'..') and (SR.Attr<>faDirectory) then
          AList.Add(ADirectory+SR.Name)
    until FindNext(SR)<>0;
    FindClose(SR);
  end;

  if ARekursiv then
    if (FindFirst(ADirectory+'*.*',faDirectory,SR)=0) then
    begin
      repeat
        if (SR.Name<>'.') and (SR.Name<>'..') then
          GetFilesInDirectory(ADirectory+SR.Name,AMask,AList,True);
      until FindNext(SR)<>0;
      FindClose(SR);
    end;
end;

procedure TForm1.btnSearchClick(Sender: TObject);
begin

lbAusgabe.Clear;
GetFilesInDirectory(DriveComboBox1.Drive+':\','*'+eSearch.Text+'*.mp3',lbAusgabe.Items,True);


end;
Grüße
Holger

Zacherl 1. Sep 2006 12:27

Re: Fortschrittsanzeige beim Durchsuchen der Festplatte
 
Dann müsstest du aber zweimal suchen ... ein Beipsiel zum Suchen von Dateien mit Progressbar findest du in der CodeLib.

Florian

Luckie 1. Sep 2006 12:28

Re: Fortschrittsanzeige beim Durchsuchen der Festplatte
 
Das geht so nicht, denn woher willst du wissen wie viele datein du findest, um den maximalen Wert zu setzen?

Es geht nur mit einem kleinen Trick: http://www.michael-puff.de/Developer/Delphi/Sonstiges -> FindAllFilesProgress_Demo.zip

DGL-luke 1. Sep 2006 12:29

Re: Fortschrittsanzeige beim Durchsuchen der Festplatte
 
Also ich würd mir die Gesamtgröße der Festplatte/des ordners holen und den Fortschritt anhand des verhältnis' durchsuchter speicherplatz/vorhandener belegter speicherplatz berechnen.

himitsu 1. Sep 2006 12:41

Re: Fortschrittsanzeige beim Durchsuchen der Festplatte
 
Bei der gesamten Festplatte hat DGL-luke schon fast Recht.
Auch wenn die den belegten Speicher der Ordner, alternativen Datenströme, MFT, gesperrter Ordner u.s.w nicht mir einrechnen kannst.

"belegter Speicher", oder "Gesammtspeicher" - "freier Platz" = Proggresbar.Max

dann wärend dem Durchsuchen alle gefundenen Dateigrößen zusammenrechnen = Proggresbar.Position


Natürlich mstest du noch 'nen Divisor einbauen, da die Platte bestimmt größer als 2 GB ist ;)


Oder mal so als Tipp: versuch dir mal zu überlegen wie ich das gelöst hab ... is garnicht sooo schwer und die Lösung urde weiter oben schon mehrmals fast so ähnlich vorgeschlagen :roll:
> http://www.delphipraxis.net/internal...117&highlight=

(kannst ja zum Test beidemal das Laufwerk "X:\" angeben ^^)




PS: die Größe eines Ordners kann man sich nicht holen
nur bei der gesamten Festplatte kann ganz schnell die anzahl der freien Cluster us dem Fesplattenbitmap ausgelesen und mit der Clustergröße multipliziert werden.

Luckie 1. Sep 2006 12:43

Re: Fortschrittsanzeige beim Durchsuchen der Festplatte
 
Zitat:

Zitat von DGL-luke
Also ich würd mir die Gesamtgröße der Festplatte/des ordners holen und den Fortschritt anhand des verhältnis' durchsuchter speicherplatz/vorhandener belegter speicherplatz berechnen.

Wenn man die gesamte Festplatte durchsucht, ist das kein Problemn, da gibt es eine API-Funktion, aber für einen Ordner musst du ja doch wieder erst alle Dateien durchgehen und deren Größe bestimmen.

DGL-luke 1. Sep 2006 12:48

Re: Fortschrittsanzeige beim Durchsuchen der Festplatte
 
Stimmt. Der Explorer rechnet da ja auch alles zusammen...

@himitsu: Entweder "Luke"/"Lukas"/"DGL-Luke" oder "Luckie", aber bitte nicht "Luck", sonst kommen wir hier leicht zu verwechslungen... ;)

newuser01 1. Sep 2006 13:33

Re: Fortschrittsanzeige beim Durchsuchen der Festplatte
 
Also ersteinmal Danke für die schnellen Antworten Ich habe mir mal das FindAllFilesProgress_Demo.zip angesehen bei diesem Beispiel wird ja die ganze Festplatte nach allen Dateien durchsucht mit Fortschritt. Meine Frage warum das ganze neu erfinden könnte man diese Funktion nich umbauen so das nicht alle Files aufgelistet werden sondern nur bestimmte die gesucht (DriveComboBox1.Drive+':\','*'+eSearch.Text +'*.mp3') werden ?

also nicht ThreadParams.Mask := '*.*';
sondern ThreadParams.Mask :=DriveComboBox1.Drive+':\','*'+eSearch.Text +'*.mp3'

Ich habe es schon so versucht erst wird die Platte durchsucht und alles in eine ListBox eingetragen mit dem Code aus dem Demo und danach übergebe ich Count dieser ListBox der Progressbar.Max und führe anschließend meinen Code aus und suche bestimmte dateien Das funktioniet ist aber nicht besonders schön da die Aktion (Suchen) nicht genau zeitgleich mit der Aktion (Fortschritt) ist


//Auszug aus dem Demo
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  ThreadParams          : PThreadParams;
begin
  RichEdit1.Clear;
  New(ThreadParams);
  try
    ThreadParams.Handle := Handle;
    ThreadParams.RootFolder := Edit1.Text;
    ThreadParams.Mask := '*.*';
    ThreadParams.Recurse := True;
    ThreadParams.Progress := True;
    WaitForThread(@ThreadFunc, ThreadParams);
  except
    on E: Exception do ShowMessage(E.Message);
  end;
end;

Grüße
Holger

himitsu 1. Sep 2006 13:43

Re: Fortschrittsanzeige beim Durchsuchen der Festplatte
 
Das Problem ist, wenn du nur suchst, dann bist du schneller du suchst gleich richtig und zählst erst garnicht nach.

Sowas lohnt sich im Grunde nur, wenn noch was Zeitaufwenigeres nebenher gemacht wird, also z.B. die Dateiinhalte auch noch mit eingelesen werden.

Denn dann ist das Zählen wesendlich schneller und zeigt auch irgendwann einen Erfolg.


Derzeit laß ich ja die kleinen Strich durchlaufen ... hatte vorher den Balken komplett, also akutell gefundene/verarbeitete Dateien im Verhältnis zu den bisher Gezählten. Ist auch 'ne Möglichkeit, da man schon wärend des Zählens einen kleinen "Erfolg" sieht.


Luckies FindAllFiles zählt z.B. erstmal alles und geht dann durch.
Vorteil: ist schneller, weil nicht 2 Leseprozesse die Platte gleichzeitig belasten.
Nachteil: der Code hängt am Anfang schonmal recht lange (der zählt ja erstmal und man sieht garnüschts)

newuser01 1. Sep 2006 13:59

Re: Fortschrittsanzeige beim Durchsuchen der Festplatte
 
Ok eine Fortschrittanzeige wäre vielleicht nicht so von Vorteil wegen der Geschwindigkeit aber wäre in meinem Code zb: ein Label möglich was den Status anzeigt also in welchem Ordner gerade gesucht wird ?

Gruß
Holger

himitsu 1. Sep 2006 14:12

Re: Fortschrittsanzeige beim Durchsuchen der Festplatte
 
Möglich wäre das, du solltest aber wenn du von einem Thread heraus auf das Label/die Form zugreifst den Zugriff synchronisieren.

Es kann sonst zu netten Zugriffsverletzungen kommen.

TThread bietet dir dazu die Prozeduren Synchronize an, oder du sendest halt per SendMessage den Ordnernamen an die Form.



Mein altes Programm zum Verzeichnisse vergleichen arbeitete z.B. nicht in einem Thread.

Die Suchprozedur war direkt im OnClick des Start-Buttons, wo dann alle ein paar 100 Millisekunden das Label beschrieben und danach Application.Proggresmessages zum Aktualisieren der Form aufgerufen wurde.

newuser01 3. Sep 2006 20:53

Re: Fortschrittsanzeige beim Durchsuchen der Festplatte
 
Hallo

Ich habe es ersteinmal so gelöst das in der Prozedur der Ordnername an Form1.Caption übergeben wird damit hätte man eine kleine Statusanzeige zumindetst sieht man das was passiert. Der Nachteil ist das die Suchaktion dadurch doppelt so lange dauert :(

Delphi-Quellcode:

procedure GetFilesInDirectory(ADirectory: string; AMask: String; AList: TStrings; ARekursiv: Boolean);
var
  SR: TSearchRec;
begin
  if (ADirectory<>'') and (ADirectory[length(ADirectory)]<>'\') then
    ADirectory:=ADirectory+'\';

  if (FindFirst(ADirectory+AMask,faAnyFile-faDirectory,SR)=0) then begin
    repeat
      if (SR.Name<>'.') and (SR.Name<>'..') and (SR.Attr<>faDirectory) then
          AList.Add(ADirectory+SR.Name)
    until FindNext(SR)<>0;
    FindClose(SR);
  end;

  if ARekursiv then
    if (FindFirst(ADirectory+'*.*',faDirectory,SR)=0) then
    begin
      repeat
        if (SR.Name<>'.') and (SR.Name<>'..') then
          GetFilesInDirectory(ADirectory+SR.Name,AMask,AList,True);
          Form1.Caption := ADirectory; //Aktuelle Ordnername wird an Caption übergeben
      until FindNext(SR)<>0;
      FindClose(SR);
    end;
end;

procedure TForm1.btnSearchClick(Sender: TObject);
begi

lbAusgabe.Clear;
GetFilesInDirectory(DriveComboBox1.Drive+':\','*'+eSearch.Text+'*.mp3',lbAusgabe.Items,True);


end;
Gruß
Holger

himitsu 4. Sep 2006 13:07

Re: Fortschrittsanzeige beim Durchsuchen der Festplatte
 
Liste der Anhänge anzeigen (Anzahl: 3)
Das liegt daran, das du jedes erzeichnis anzeigst, welches ganz schön bremst.

Entweder du zeigst das nur alle 'ner gewissen Zeit (welches is inzwischen bevorzuge),
oder nur jedes x-te Verzeichnis an.


per Zeitintervall:
-Vorteil: unterumständen schwerer zu implementieren
-Nachteil: überall etwa gleiches Anzeigeverhalten

jedes x-te:
-Vorteil: ganz leichte Implementierung
Delphi-Quellcode:
// zu Begin
X := 0;

// bei jedem Durchgang
Inc(X);
If X and $1F = 0 Then anzeigen; // jedes 32. Mal
-Nachteil:
auf schnellen Rechnern kann das Intervall zu kurz sein und die Anzeige bremst dennoch aus.
Und auf langsamen PCs, oder anderweiligen Verzögerungen kann die Aktualisierung der Anzeige schonmal recht große Pausen einlegen.


Hab mal ein bissl rumkompiliert..
Die Sync-Version zeigt auch jede Kleinigkeit an und ist daher langsamer.
Bei der Timer wird nur nach mindestens 100ms angezeigt (außerdem wurde dort für den ZählThread die CPU-Zeit und der Laufwerkszugriff optimiert).
Und in der Timer_ sind keine Optimierungen und die ProgressBar wird als solche angezeigt ... man wird da schonal leicht sehen können, daß da die ProgressBar rückwärts gehen und auch gewaltige Sprünge machen kann. (weßhalb ich wärend des Zählens die Bar eigentlich "ausblende")

Zum Test reicht es, wie schonmal erwähnt, wenn man beide Male das selbe Laufwerk angibt ... z.B. "C:\"

newuser01 4. Sep 2006 18:23

Re: Fortschrittsanzeige beim Durchsuchen der Festplatte
 
Hallo "himitsu" Danke für deine Hilfe !

Die Idee mit dem jedes x. mal habe ich übernommen das funktioniert am besten und es ist kaum ein Geschwindigkeitsverlust zu spüren denn das Programm läuft in dem Falle eh nur auf einem Rechner. Zwei Fragen habe ich aber noch was bedeutet "and $1F" und wie hast du das hinbekommen mit der Progressbar das sie immer hin und her links rechts so wie in Windows beim suchen geht ?

Grüße
Holger


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:47 Uhr.

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