Autor Beitrag
ggehrma
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 111

WinXP
D2005 Pers.
BeitragVerfasst: Mi 29.06.05 14:59 
Hallo,

In meinem Programm möchte ich die Dateien in einem Verzeichnis und dessen Unterverzeichnisse zählen. Dabei sollen einmal alle Dateien insgesamt gezähl werden und die Dateien der jeweiligen Endung. Dazu habe ich bisher folgenden Code:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
CONST
  Ext: Array[0..7] OF String = ('*.dll', '*.exe', '*.sys',
             '*.bmp', '*.gif', '*.jpg', 'sonstige', 'gesamt');

var
  Anzahl: Array[0..7] OF INTEGER;
  Size: Array[0..7] OF INT64;

procedure GetFilesInDirectory(ADirectory: string; AMask: String; AList: TListView; ARekursiv: Boolean);
var
  i: INTEGER;
  j: INTEGER;
  SR: TSearchRec;
  FileExt: String;
begin
  IF (ADirectory<>'') and (ADirectory[length(ADirectory)]<>'\') then
    ADirectory:=ADirectory+'\';
  If ADirectory = '' THEN
    ADirectory := GetCurrentDir + '\';
  IF (FindFirst(ADirectory+AMask,faAnyFile-faDirectory,SR)=0) then begin
    repeat
      if (SR.Name<>'.') and (SR.Name<>'..') and (SR.Attr<>faDirectory) then
        BEGIN
          FileExt := Copy(SR.Name,Length(SR.Name)-2,3);
          FOR i := 0 TO 5 DO
            IF FileExt = Copy(Ext[i],3,3) THEN BEGIN
              j := i;
              break;
            END;
          IF j <= 5 THEN BEGIN
            Anzahl[j] := Anzahl[j] + 1;
            Size[j] := Size[j] + SR.Size;
          END ELSE BEGIN
            Anzahl[6] := Anzahl[6] + 1;
            Size[6] := Size[6] + SR.Size;
          END;
        END;
    until FindNext(SR)<>0;
    frmWait.Refresh;
    FindClose(SR);
  end;


Mein Problem ist jetzt, dass falsch gezählt wird. Die Summe der einzelnen Anzahlen stimmt zwar, aber die einzelnen Anzahlen selber nicht. So wird mir z.B. angezeigt, dass in einem Verzeichnis 6 *.exe Dateien sind, obwohl nur eine *.exe Datei in diesem Verzeichnis ist.

Wo liegt mein Fehler. Bitte helft mir.

Danke.
mfg, ggehrma

Moderiert von user profile iconraziel: Code- durch Delphi-Tags ersetzt.
Moderiert von user profile iconGausi: Topic aus VCL (Visual Component Library) verschoben am Mi 29.06.2005 um 18:28
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 29.06.05 15:42 
Moin!

user profile iconggehrma hat folgendes geschrieben:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
          IF j <= 5 THEN BEGIN
            Anzahl[j] := Anzahl[j] + 1;
            Size[j] := Size[j] + SR.Size;
          END ELSE BEGIN
            Anzahl[6] := Anzahl[6] + 1;
            Size[6] := Size[6] + SR.Size;
          END;


Mein Problem ist jetzt, dass falsch gezählt wird. Die Summe der einzelnen Anzahlen stimmt zwar, aber die einzelnen Anzahlen selber nicht. So wird mir z.B. angezeigt, dass in einem Verzeichnis 6 *.exe Dateien sind, obwohl nur eine *.exe Datei in diesem Verzeichnis ist.

Lass man das markierte weg, du willst doch Gesamt in jedem Fall zählen. Ansonsten, gebe ich zu, habe ich nicht genauer hingesehen... :wink:

cu
Narses
ggehrma Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 111

WinXP
D2005 Pers.
BeitragVerfasst: Mi 29.06.05 15:45 
Das hättest du aber tun sollen. Dann hättest du nämlich gesehen, dass Anzahl[6] die sonstigen Endungen zählt. Erst Anzahl[7] zählt gesamt.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 29.06.05 15:50 
user profile iconggehrma hat folgendes geschrieben:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
        BEGIN
          FileExt := Copy(SR.Name,Length(SR.Name)-2,3);
          j := 6;
          FOR i := 0 TO 5 DO
            IF FileExt = Copy(Ext[i],3,3) THEN BEGIN
              j := i;
              break;
            END;
          IF j <= 5 THEN BEGIN
            Anzahl[j] := Anzahl[j] + 1;
            Size[j] := Size[j] + SR.Size;
          END ELSE BEGIN
            Anzahl[6] := Anzahl[6] + 1;
            Size[6] := Size[6] + SR.Size;
          END;
        END;

Jaja, du hast ja recht, probier das mal. :wink:

cu
Narses
ggehrma Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 111

WinXP
D2005 Pers.
BeitragVerfasst: Mi 29.06.05 16:02 
Jetzt werden zum Teil zu viele gezählt und zum Teil zu wenig.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 29.06.05 16:12 
user profile iconggehrma hat folgendes geschrieben:
Jetzt werden zum Teil zu viele gezählt und zum Teil zu wenig.

Hmm, also jetzt wird´s langsam schwierig... :wink: Ausser, dass du:
- die Anzahlen am Anfang nicht initialisierst (=0 setzen!) und
- Copy verwendest, statt der entsprechenden Funktion zum extrahieren des Extenders,
fällt mir da nix "falsches" mehr auf.

Müßte ich jetzt den Code mal selbst ausprobieren; kann ich aber erst heute abend, bin noch auf´m Job... :wink:

cu
Narses
ggehrma Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 111

WinXP
D2005 Pers.
BeitragVerfasst: Mi 29.06.05 16:23 
wie wäre denn die entsprechende Funktion zum extrahieren des Extenders? Initialisiert werden die Anzahlen am Anfang. Passiert nur in einer anderen Procedur und wurde deshalb nicht mit kopiert.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 29.06.05 22:16 
Moin!

So, probier das mal:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
const
  Ext: Array[0..6] of String = ('.DLL', '.EXE', '.SYS', '.BMP', '.GIF', '.JPG', '*');

var
  Anzahl: Array[0..7] of Integer;
  Size: Array[0..7] of Int64;

procedure GetFilesInDirectory(ADirectory: String);
  var
    i: Integer;
    SR: TSearchRec;
    FileExt: String;

  procedure CountElement(i: Integer);
  begin
    Inc(Anzahl[i]);
    Size[i] := Size[i] +SR.Size;
  end;

begin
  if (ADirectory = '') then
    ADirectory := GetCurrentDir;
  ADirectory := IncludeTrailingPathDelimiter(ADirectory);
  if (FindFirst(ADirectory +'*.*', faAnyFile -faDirectory, SR) = 0) then
    repeat
      if ( (SR.Name <> '.') and
           (SR.Name <> '..') and
           (SR.Attr <> faDirectory) ) then begin
        FileExt := UpperCase(ExtractFileExt(SR.Name));
        CountElement(7); // Gesamtanzahl aktualisieren
        i := 0;
        while ( (i < 6) and (FileExt <> Ext[i]) ) do
          Inc(i);
        CountElement(i); // Spezialanzahl aktualisieren
      end;
    until (FindNext(SR) <> 0);
  FindClose(SR);
end;

Bei mir klappt das jetzt einwandfrei.

cu
Narses
ggehrma Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 111

WinXP
D2005 Pers.
BeitragVerfasst: Do 30.06.05 13:29 
Hallo,

bei mir leider immernoch nicht. Es werden generell zu wenig Dateien gezählt. Mal nur eine zu wenig, aber mal auch nur die Hälfte. Und die Gesamtanzahl wird doppelt gezählt.

cu, ggehrma.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 30.06.05 22:08 
Moin!

user profile iconggehrma hat folgendes geschrieben:
bei mir leider immernoch nicht. Es werden generell zu wenig Dateien gezählt. Mal nur eine zu wenig, aber mal auch nur die Hälfte. Und die Gesamtanzahl wird doppelt gezählt.

Bist du sicher, dass du meinen Code korrekt übernommen hast?! Ich glaube nicht, deshalb hier mein Projekt im Anhang; probier´s aus, es klappt einwandfrei! :wink:

cu
Narses
Einloggen, um Attachments anzusehen!
ggehrma Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 111

WinXP
D2005 Pers.
BeitragVerfasst: Fr 01.07.05 15:14 
Also ich hab jetzt alles nach besstem Wissen und Gewissen von dir übernommen. Aber leider bekomme ich immernoch eine Fehlermeldung :cry: . Hab jetzt mal mein komplettes Programm angehängt. Vielleicht findest du ja den Fehler.

mfg, ggehrma
Einloggen, um Attachments anzusehen!
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Fr 01.07.05 20:52 
Moin!

So, hab das Programm "mal eben" etwas "korrigiert". Hier die Liste der Änderungen, ähm, naja, soweit ich noch Bock hatte, mitzuschreiben...


  1. Praktisch niemals(!) Halt; verwenden, immer (in VCL-Apps) Application.Terminate;!
  2. Wenn man auf Tastendrücke als Aktion reagieren will, ist OnKeyPress() besser als OnKeyDown().
  3. Wozu *.* übergeben, wenn du immer *.* verwendest? Hab´s rausgenommen.
  4. Du hast IncludeTrailingPathDelimiter() an diversen Stellen "unterschlagen". :wink:
  5. Das FindClose() ist (immer noch) eine if-ebene "zu tief" gewesen!
  6. Dein Programm "steht" beim Scannen; habe deshalb einen Stop-Button und Application.ProcessMessages mit Verzögerung reingenommen; besser ist natürlich ein Scanner-Thread; aber du sollst ja auch noch was "zu tun" haben... :wink:
  7. Du solltest den VCL-Kompos mal "ordentliche" Namen geben, dann hat man etwas mehr Überblick.
  8. Du kannst die Spalten doch auch direkt in die ListViews eintragen, die ändern sich doch nicht dynamisch; habe sowieso etwas an der GUI "gespielt"... :wink:
  9. Es ist natürlich generell keine gute Idee, einem ListView soviele Elemente zuzuweisen! DAS ist auch dein Speicherfresser und nicht die Felder (die du nebenbeigesagt sowieso nicht brauchst); abgesehen davon macht es keinen Sinn, alle Dateien aufzulisten, das braucht eh keiner, weil das so viel ist, dass es einen "erschlägt" :? Und es macht den Scanvorgang nur unnötig grausam langsam (C:\ scannen dauert bei mir ohne die Dateien ins ListView zu prügeln ca. 3sec.; mit Dateien einfügen Minuten...)
  10. Du hast da einen Haufen Arrays für ListView-Einträge verwendet, die du gar nicht brauchst; warum die Einträge nicht einfach direkt ins ListView einstellen?
  11. Du solltest in der Grafik besser mit TextOut arbeiten, nicht mit dynamischen Labels; wenn du dynamisch auf Resize-Events reagieren willst, kriegst du Probleme mit deiner jetzigen Code-Struktur!

Ich habe die Grundstruktur des Programms dahingehend "verändert", dass die Liste der Extender jetzt "pseudo-dynamisch" ist. Heißt: du fügst einfach weitere Extender in die const-Liste ein oder nimmst welche raus, das "restliste Programm" kommt damit ohne Änderungen klar, weil die entsprechend nötigen Datenstrukturen dynamisch angelegt werden. Lediglich deine Grafikroutinen habe ich nur soweit angepasst, dass es mit der aktuellen Anzahl Extender klappt; hier wäre noch von dir "Nacharbeit" nötig... :wink:

Wenn du Fragen zu einem Code-Stück hast, immer her damit; soll ja auch was bei rumkommen, für dich, nicht nur fertiger Code... :wink:

cu
Narses
Einloggen, um Attachments anzusehen!
ggehrma Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 111

WinXP
D2005 Pers.
BeitragVerfasst: Sa 02.07.05 13:35 
Hallo,

erstmal danke für die Arbeit, die du dir gemacht hast. Hab aber mal ein paar Fragen/Anmerkungen zu deinem Programm:

- Die Pointer hab ich versucht zu umgehen, da ich mich damit nicht so wirklich auskenne.
- Warum hast du meine Unit2, also das Nachrichtenfenster für die Meldung, dass der
angegebene Pfad gescannt wird rausgelöscht?
- Deine Änderungen an der GUI find ich nicht ganz so in Ordnung. hab mir da nämlisch
schon was bei gedacht.
- leider werden bei mir auch immernoch nicht alle Dateianzahlen korrekt gezählt. Bei
einigen Endungen werden immernoch zu wenig angezeigt.

cu, ggehrma.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: So 03.07.05 02:15 
Moin!

user profile iconggehrma hat folgendes geschrieben:

- Warum hast du meine Unit2, also das Nachrichtenfenster für die Meldung, dass der
angegebene Pfad gescannt wird rausgelöscht?

Weil es nix bringt (bzw. brachte) und die framebasierte Umsetzung fehlerhaft/umständlich/überflüssig war. Besser wäre eh ein Thread, der den MainFrame nicht blockiert.

user profile iconggehrma hat folgendes geschrieben:
- Deine Änderungen an der GUI find ich nicht ganz so in Ordnung. hab mir da nämlisch
schon was bei gedacht.

Im Kommentar steht "meine Version". Du musst meine Vorschläge weder gut finden noch übernehmen. Ignorier es einfach, wenn´s dir nicht passt.

user profile iconggehrma hat folgendes geschrieben:
- leider werden bei mir auch immernoch nicht alle Dateianzahlen korrekt gezählt. Bei
einigen Endungen werden immernoch zu wenig angezeigt.

Ich kann nur wiederholen: bei mir werden alle Dateien sowohl korrekt erkannt, als auch korrekt gezählt. Was diese Fehlfunktion bei dir bewirkt, ist mir ehrlich gesagt schleierhaft... :gruebel: Mach doch mal Testausgaben in eine Logdatei beim Scannen, oder so. Wie soll man sonst dem Problem auf die Spur kommen... ? IMHO ist der Code fehlerfrei, bei mir geht´s ja auch, wie gesagt.

Wie dir vielleicht auffällt, "bemäkelst" du nur Dinge, die die GUI betreffen (wenn man mal von dem ominösen Fehler absieht; aber da kommen wir nur mit der Aussage: bei mir klappt´s immer noch nicht, nicht wirklich weiter); offensichtlich sind meine "Anpassungen" der Code-Grundstruktur schon "gut" bei dir angekommen, hm? :wink: Wenn dem so sein sollte, habe ich mein Ziel erreicht; wie deine GUI aussieht, ist mir ehrlich gesagt schnuppe.

cu
Narses

//EDIT: Nun, was los? Wolln wir jetzt noch rausfnden, warum das bei dir nicht klappt, oder kein Bock mehr?
ggehrma Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 111

WinXP
D2005 Pers.
BeitragVerfasst: Mi 06.07.05 11:51 
Hallo,

hab mich jetzt mal genauer an dein Programm gesetzt.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure TfrmMain.FormCreate(Sender: TObject);
  var
    i: Integer;
    ExtDetails: PExtDetails;
begin
  Ext := TStringList.Create;
  Ext.CommaText := EXT_LIST; // Endungen einlesen
  for i := 0 to Ext.Count-1 do begin // und Details-record anlegen
    New(ExtDetails);
    Ext.Objects[i] := TObject(ExtDetails);
  end;
  // aktuellen Pfad eintragen
  txtPath.Text := IncludeTrailingPathDelimiter(GetCurrentDir);
end;


Das TObject(ExtDetails) reserviert Speicher für Ext.Objects, oder?

Moderiert von user profile iconraziel: Code- durch Delphi-Tags ersetzt.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 06.07.05 12:55 
Moin!

user profile iconggehrma hat folgendes geschrieben:
Das TObject(ExtDetails) reserviert Speicher für Ext.Objects, oder?

Nein, das ist nur eine Typumwandlung (typecast).

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
procedure TfrmMain.FormCreate(Sender: TObject);
  var
    i: Integer;
    ExtDetails: PExtDetails;
begin
  Ext := TStringList.Create;
  Ext.CommaText := EXT_LIST; // Endungen einlesen
  for i := 0 to Ext.Count-1 do begin // und Details-record anlegen
    New(ExtDetails); // Speicherplatz reservieren
    Ext.Objects[i] := TObject(ExtDetails); // Zeiger darauf merken
  end;
  // aktuellen Pfad eintragen
  txtPath.Text := IncludeTrailingPathDelimiter(GetCurrentDir);
end;

[...]

procedure TfrmMain.FormDestroy(Sender: TObject);
  var
    i: Integer;
begin
  // Details-records entsorgen
  for i := 0 to Ext.Count-1 do
    Dispose(PExtDetails(Ext.Objects[i])); // den mit New() reservierten Speicher wieder freigeben
  Ext.Free; // und die Liste selbst entsorgen
end;

Das TObject(ExtDetails) ist nur deshalb nötig, weil Ext.Objects[] ein Array of TObject ist, das sind zwar auch "nur" Zeiger, aber eben ein anderer Typ. Und damit der Compiler "zufrieden" ist, macht man einen Typecast.

cu
Narses
ggehrma Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 111

WinXP
D2005 Pers.
BeitragVerfasst: Mi 06.07.05 15:27 
Was habe ich hier falsch gemacht?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
TYPE
  TExtDetails = RECORD
    Anzahl: INT64;
    Size: INT64;
//    Prozent: DOUBLE;
    TProzent: RECORD
      Anzahl: DOUBLE;
      Size: DOUBLE;
    END;
    PProzent: ^TProzent;
  END;
  PExtDetails = ^TExtDetails;


Wie schon geschrieben kenne ich mich nicht so wirklich gut mit Records und Pointern aus. Aber ich bin mir ziemlich sicher, dass es möglich ist Records zu verschachteln. Aber so wie ich es hab geht es offensichtlich nicht.

Moderiert von user profile iconGausi: Code- durch Delphi-Tags ersetzt.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 06.07.05 16:48 
Moin!

user profile iconggehrma hat folgendes geschrieben:
Was habe ich hier falsch gemacht?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
TYPE
  TExtDetails = RECORD
    Anzahl: INT64;
    Size: INT64;
    Prozent: RECORD // so wäre die Datenstruktur korrekt zu deklarieren
      Anzahl,
      Size: DOUBLE;
    END;
  END;
  PExtDetails = ^TExtDetails; // das hier ist nur ein Zeiger auf den record-Typ

Wenn ich mir das so ansehe, habe ich allerdings Zweifel, dass du da was "Sinnvolles" tust... :wink:

cu
Narses
ggehrma Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 111

WinXP
D2005 Pers.
BeitragVerfasst: Do 07.07.05 12:12 
Das hat schon alles seinen Sinn. Glaub mir.

Andere Frage: Gibt es eigentlich die Möglichkeit auch versteckte Ordner und Dateien zu zählen, ohne diese konkret anzugeben?
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 07.07.05 18:28 
Moin!

user profile iconggehrma hat folgendes geschrieben:
Gibt es eigentlich die Möglichkeit auch versteckte Ordner und Dateien zu zählen, ohne diese konkret anzugeben?

Du spielst auf "Recycled" und "System Volume Information" an, oder? Da es sich bei diesen beiden Ordnern um spezielle (Explorer-)Systemobjekte handelt, weiss ich das nicht so genau. Aber mit faAllFiles werden schon alle Dateien und Ordner ausgesucht.

cu
Narses