Seite 1 von 1

Dateien rekursiv zählen und Namen in Array speichern ;-)

Verfasst: 07.09.2008 15:02
von K.Putt
Hallo,
ich wollte das eigentlich kurz in wenigen Minuten programmieren, nun sitze ich seit 3 Sunden daran und finde trotz Code-Archiv ud Forum keine Lösung.

Ich möchte die Dateinamen eines Verzeichnisse inkl. aller Unterverzeichnisse in einem Array speichern.

Dafür benötige ich natürlich einen Zähler um das Array zu ReDimensionieren und den Eintrag zuzuweisen -
und genau hier ist der Haken, ich bekomme den Zähler nicht korrekt zum Laufen.

Ich habe mal folgendes aus dem Code Archiv und exemplarisch einen DEBUG hinzugefügt - dieser spiegelt das Problem wieder an dem ich hänge, trotz vieler Code-Variationen mittlerweile.

Code: Alles auswählen

Procedure.l CountFiles(Dir.s) 
   Protected ID.l, files.l 

   If Right(Dir, 1) <> "\" 
      Dir + "\" 
   EndIf 

   ID = ExamineDirectory(#PB_Any, Dir, "") 
   If ID 
      While NextDirectoryEntry(ID) 
         Select DirectoryEntryType(ID) 
            Case 0 
               Break 
            Case #PB_DirectoryEntry_File 
              Debug files ; <- Hier sollte das Array gefüllt werden ;-)
              files + 1 
            Case #PB_DirectoryEntry_Directory 
               If DirectoryEntryName(ID) <> "." And DirectoryEntryName(ID) <> ".." 
                  files + CountFiles(Dir + DirectoryEntryName(ID)) 
               EndIf 
         EndSelect 
      Wend 
   EndIf 

   ProcedureReturn files 
EndProcedure 

Dir.s = PathRequester("Pfad auswählen...", "C:\") 

If Dir 
   files.l = CountFiles(Dir) 
   MessageRequester(Dir, "Das Verzeichnis enthält " + Str(files) + " Dateien und Verzeichnisse.") 
EndIf 
Das Problem ist, dass man ohne die Rekursion nicht die Unterverzeichnisse durchlaufen kann, wie in diesem Beispiel aber deutlich - der Zähler nur den Gesamtoutput korrekt ausgibt, innerhalb der Funktion aber nicht auf die Art funktioniert, dass man damit ein Array füllen kann.

Ich bin für jeden Vorschlag dankbar, von mir aus kann es auch anders gelöst werden (LinkedList ?)...

Re: Dateien rekursiv zählen und Namen in Array speichern ;-)

Verfasst: 07.09.2008 15:28
von Little John
K.Putt hat geschrieben:

Code: Alles auswählen

If Dir 
   files.l = CountFiles(Dir) 
   MessageRequester(Dir, "Das Verzeichnis enthält " + Str(files) + " Dateien und Verzeichnisse.") 
EndIf 
Nebenbei: Die Verzeichnisse werden in obigem Code nicht gezählt, sondern nur die Dateien.
K.Putt hat geschrieben:Das Problem ist, dass man ohne die Rekursion nicht die Unterverzeichnisse durchlaufen kann, wie in diesem Beispiel aber deutlich - der Zähler nur den Gesamtoutput korrekt ausgibt, innerhalb der Funktion aber nicht auf die Art funktioniert, dass man damit ein Array füllen kann.

Ich bin für jeden Vorschlag dankbar, von mir aus kann es auch anders gelöst werden (LinkedList ?)...
Das einfachste ist, eine globale Linked List zu nehmen. Und wo im Programm

Code: Alles auswählen

files + 1
vorkommt, hängst Du den entspr. Namen an die Liste ran.

Gruß, Little John

Verfasst: 07.09.2008 15:42
von K.Putt
Hallo und Danke!
ich habe gerade auch versucht es mit Globals zu lösen, geht tatsächlich.
Ich benutze allerdings sehr ungern globale Variablen, eventuell findet Jeman bei Interesse ja noch elegantere Lösungen.

Code: Alles auswählen


Global Dim Array_Files.s(0)
Global filecounter

Declare Get_Directory(path$)
Declare Fill_Array(filename$)

directory$ = PathRequester("Path", "C:\")

Get_Directory(directory$);

SortArray(Array_Files(),#PB_Sort_Ascending)
For i = 0 To filecounter-1
	Debug "Array Element: " + Str(i)+ Array_Files(i)
Next

Procedure Fill_Array(filename$)	
 	ReDim Array_Files.s(filecounter)
 	Array_Files(filecounter)=filename$
 	filecounter+1
EndProcedure

Procedure Get_Directory(EntryPath.s) 
   ID = ExamineDirectory(#PB_Any, EntryPath, "") 
   If ID 
      While NextDirectoryEntry(ID) 
         Select DirectoryEntryType(ID) 
            Case 0 
               Break 
            Case #PB_DirectoryEntry_Directory 
               If DirectoryEntryName(ID) <> "." And DirectoryEntryName(ID) <> ".." 
                  Get_Directory(EntryPath + DirectoryEntryName(ID)+ "\") 
               EndIf                              
            Case #PB_DirectoryEntry_File               
	   			Fill_Array(DirectoryEntryName(ID))                        
         EndSelect 
      Wend 
   EndIf 
   FinishDirectory(ID) 	
EndProcedure 

Verfasst: 07.09.2008 15:54
von STARGÅTE
wieso nutzt du kein ProcedureReturn ?

du zählst deine Files in einer Procedure (also nicht global)

und gibs die menge am ende der procedure mit ProcedureReturn an die "Eltern"-Procedure zurück, dieser addiert dann diese Menge zu ihrern Fils hinzu usw.

am ende erhälst du den Rückgabe wert

Verfasst: 07.09.2008 15:57
von K.Putt
Ähhhhmmmm...

Gute Idee, Danke! :allright:

Ich bin nicht so geübt im Nutzen von Rückgabewerten. :oops:

Halt, kleine Frage....
In der Child-Procedure brauche ich dann doch auch einen globalen Zähler oder nicht?

Verfasst: 07.09.2008 15:58
von Little John
K.Putt hat geschrieben:ich habe gerade auch versucht es mit Globals zu lösen, geht tatsächlich.
Ich benutze allerdings sehr ungern globale Variablen,
Wenn Du die Namen nur innerhalb der Prozedur brauchtst, kannst Du auch Static nehmen. Ansonsten sollte ein Shared Array bzw. Linked List auch gehen. Du kannst auch das Array bzw. die Linked List als Parameter übergeben.

Gruß, Little John

Verfasst: 07.09.2008 16:00
von Little John
STARGÅTE hat geschrieben:wieso nutzt du kein ProcedureReturn ?
Das hat er in seinem ersten Code ja gemacht. Aber damit kann man kein Array bzw. eine Linked List (mit den Namen) zurückgeben, oder doch?

Gruß, Little John

Verfasst: 07.09.2008 16:02
von STARGÅTE
so wäre das :

Code: Alles auswählen

Global Dim Array_Files.s(0) 

Declare Get_Directory(path$) 
Declare Fill_Array(filename$, filecounter) 

directory$ = PathRequester("Path", "C:\") 

filecounter = Get_Directory(directory$); 

SortArray(Array_Files(),#PB_Sort_Ascending) 
For i = 0 To filecounter-1 
   Debug "Array Element: " + Str(i)+ Array_Files(i) 
Next 

Procedure Fill_Array(filename$, filecounter)    
    ReDim Array_Files.s(filecounter) 
    Array_Files(filecounter)=filename$ 
   ProcedureReturn 1
EndProcedure 

Procedure Get_Directory(EntryPath.s) 
   ID = ExamineDirectory(#PB_Any, EntryPath, "") 
   If ID 
      While NextDirectoryEntry(ID) 
         Select DirectoryEntryType(ID) 
            Case 0 
               Break 
            Case #PB_DirectoryEntry_Directory 
               If DirectoryEntryName(ID) <> "." And DirectoryEntryName(ID) <> ".." 
                  filecounter + Get_Directory(EntryPath + DirectoryEntryName(ID)+ "\") 
               EndIf                              
            Case #PB_DirectoryEntry_File                
               filecounter + Fill_Array(DirectoryEntryName(ID), filecounter)                        
         EndSelect 
      Wend 
   EndIf 
   FinishDirectory(ID)     
   ProcedureReturn filecounter
EndProcedure 

Verfasst: 07.09.2008 16:06
von Little John
STARGÅTE hat geschrieben:so wäre das :
Ach so, ja. Der FileCounter braucht sowieso nicht Global zu sein.
Aber auch das Array (bzw. die Linked List) braucht nicht Global zu sein, wenn's als Parameter übergeben wird.

Gruß, Little John