| Autor |
Beitrag |
ggehrma
      
Beiträge: 111
WinXP
D2005 Pers.
|
Verfasst: 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:
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 raziel: Code- durch Delphi-Tags ersetzt.Moderiert von Gausi: Topic aus VCL (Visual Component Library) verschoben am Mi 29.06.2005 um 18:28
|
|
Narses
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 29.06.05 15:42
Moin!
ggehrma hat folgendes geschrieben: | 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...
cu
Narses
|
|
ggehrma 
      
Beiträge: 111
WinXP
D2005 Pers.
|
Verfasst: 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
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 29.06.05 15:50
ggehrma hat folgendes geschrieben: | 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.
cu
Narses
|
|
ggehrma 
      
Beiträge: 111
WinXP
D2005 Pers.
|
Verfasst: Mi 29.06.05 16:02
Jetzt werden zum Teil zu viele gezählt und zum Teil zu wenig.
|
|
Narses
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 29.06.05 16:12
ggehrma hat folgendes geschrieben: | | Jetzt werden zum Teil zu viele gezählt und zum Teil zu wenig. |
Hmm, also jetzt wird´s langsam schwierig...  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...
cu
Narses
|
|
ggehrma 
      
Beiträge: 111
WinXP
D2005 Pers.
|
Verfasst: 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
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 29.06.05 22:16
Moin!
So, probier das mal:
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); i := 0; while ( (i < 6) and (FileExt <> Ext[i]) ) do Inc(i); CountElement(i); end; until (FindNext(SR) <> 0); FindClose(SR); end; |
Bei mir klappt das jetzt einwandfrei.
cu
Narses
|
|
ggehrma 
      
Beiträge: 111
WinXP
D2005 Pers.
|
Verfasst: 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
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Do 30.06.05 22:08
Moin!
ggehrma 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!
cu
Narses
Einloggen, um Attachments anzusehen!
|
|
ggehrma 
      
Beiträge: 111
WinXP
D2005 Pers.
|
Verfasst: 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  . Hab jetzt mal mein komplettes Programm angehängt. Vielleicht findest du ja den Fehler.
mfg, ggehrma
Einloggen, um Attachments anzusehen!
|
|
Narses
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: 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...
- Praktisch niemals(!) Halt; verwenden, immer (in VCL-Apps) Application.Terminate;!
- Wenn man auf Tastendrücke als Aktion reagieren will, ist OnKeyPress() besser als OnKeyDown().
- Wozu *.* übergeben, wenn du immer *.* verwendest? Hab´s rausgenommen.
- Du hast IncludeTrailingPathDelimiter() an diversen Stellen "unterschlagen".
- Das FindClose() ist (immer noch) eine if-ebene "zu tief" gewesen!
- 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...
- Du solltest den VCL-Kompos mal "ordentliche" Namen geben, dann hat man etwas mehr Überblick.
- Du kannst die Spalten doch auch direkt in die ListViews eintragen, die ändern sich doch nicht dynamisch; habe sowieso etwas an der GUI "gespielt"...
- 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...)
- 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?
- 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...
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...
cu
Narses
Einloggen, um Attachments anzusehen!
|
|
ggehrma 
      
Beiträge: 111
WinXP
D2005 Pers.
|
Verfasst: 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
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: So 03.07.05 02:15
Moin!
ggehrma 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.
ggehrma 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.
ggehrma 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...  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?  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 
      
Beiträge: 111
WinXP
D2005 Pers.
|
Verfasst: Mi 06.07.05 11:51
Hallo,
hab mich jetzt mal genauer an dein Programm gesetzt.
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; for i := 0 to Ext.Count-1 do begin New(ExtDetails); Ext.Objects[i] := TObject(ExtDetails); end; txtPath.Text := IncludeTrailingPathDelimiter(GetCurrentDir); end; |
Das TObject(ExtDetails) reserviert Speicher für Ext.Objects, oder?
Moderiert von raziel: Code- durch Delphi-Tags ersetzt.
|
|
Narses
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 06.07.05 12:55
Moin!
ggehrma hat folgendes geschrieben: | | Das TObject(ExtDetails) reserviert Speicher für Ext.Objects, oder? |
Nein, das ist nur eine Typumwandlung (typecast).
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; for i := 0 to Ext.Count-1 do begin New(ExtDetails); Ext.Objects[i] := TObject(ExtDetails); end; txtPath.Text := IncludeTrailingPathDelimiter(GetCurrentDir); end;
[...]
procedure TfrmMain.FormDestroy(Sender: TObject); var i: Integer; begin for i := 0 to Ext.Count-1 do Dispose(PExtDetails(Ext.Objects[i])); Ext.Free; 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 
      
Beiträge: 111
WinXP
D2005 Pers.
|
Verfasst: Mi 06.07.05 15:27
Was habe ich hier falsch gemacht?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| TYPE TExtDetails = RECORD Anzahl: INT64; Size: INT64; 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 Gausi: Code- durch Delphi-Tags ersetzt.
|
|
Narses
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 06.07.05 16:48
Moin!
ggehrma hat folgendes geschrieben: | | Was habe ich hier falsch gemacht? |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| TYPE TExtDetails = RECORD Anzahl: INT64; Size: INT64; Prozent: RECORD Anzahl, Size: DOUBLE; END; END; PExtDetails = ^TExtDetails; |
Wenn ich mir das so ansehe, habe ich allerdings Zweifel, dass du da was "Sinnvolles" tust...
cu
Narses
|
|
ggehrma 
      
Beiträge: 111
WinXP
D2005 Pers.
|
Verfasst: 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
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Do 07.07.05 18:28
Moin!
ggehrma 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
|
|