Seite 1 von 2
Schnelles Zählen von Dateien
Verfasst: 19.11.2010 02:27
von MK_2007
Hallo zusammen,
ich benötige eine Funktion, die mir schnell die Anzahl von Dateien in einem Verzeichnis (ohne Unterverzeichnisse) zurück gibt. Ich habe schon unten stehenden Code ausprobiert, nur benötigt der bei ca. 5000 Dateien auf einem Netzlaufwerk ca. 45 Sekunden. Das ist leider zu lang....Gibt es eine schnellere Alternative (evtl. über API oder so)
Vielen Dank im Voraus.
Code:
Code: Alles auswählen
Procedure.l CountFiles(dir.s,pattern.s)
Protected ID.l, files.l
If Right(Dir, 1) <> "\"
Dir + "\"
EndIf
ID = ExamineDirectory(#PB_Any, Dir, pattern)
If ID
While NextDirectoryEntry(ID)
Select DirectoryEntryType(ID)
Case #PB_DirectoryEntry_File
Files+1
EndSelect
Wend
EndIf
ProcedureReturn files
EndProcedure
Edit by NicTheQuick: Code-Tags gesetzt
Re: Schnelles Zählen von Dateien
Verfasst: 19.11.2010 03:43
von PureLust
Also die einzige Möglichkeit, die ich da sehen würde wäre, wenn Du das ressourcenhungrige Zählen der Dateien durch eine kleine Routine direkt auf dem Server des Netzlaufwerkes durchführen lässt und Du Dir dann über das Netzwerk nur noch das Ergebnis auf den Client übertragen lässt.
Re: Schnelles Zählen von Dateien
Verfasst: 22.11.2010 12:12
von Blackskyliner
Windows oder Linux?
Unter Linux "ls | uniq | wc > anzahl.txt" - so oder so ähnlich...
Unter Windows "dir > ordner.txt" und dann in einer kleinen Stringverarbeitung die Zeilen zählen... k.A. ob DOS auch andere nützliche Kommandos liefert um das zu zählen...
Re: Schnelles Zählen von Dateien
Verfasst: 22.11.2010 16:02
von NicTheQuick
Ich denke das Problem ist, dass 'ExamineDirectory()' noch mehr macht als nur Dateien aufzählen. Man kann ja zum Beispiel mit der selben Library auch die verschiedenen Zeitangaben jeder Datei auslesen. Das wird aber nicht im Directory gespeichert. Dazu muss jede Datei einzeln geöffnet werden. Um nur die reine Dateianzahl eines Ordners auszugeben, würde ich an deiner Stelle auf API zugreifen bzw. Konsolenbefehle benutzen und deren Ausgaben direkt parsen.
Das ganze hängt ja damit zusammen wie das Dateisystem aufgebaut ist. Gehen wir mal von INodes aus, dann gibt es eine INode, die das Directory darstellt samt einer Liste von weiteren Inodes, die zu den eigentlichen Dateiinhalten linken. Und eigentlich musst du ja nur die Anzahl der INodes zählen, die keine Directories sind. Dazu gibt es je nach Dateisystem dann schon direkt im Listing des übergeordneten Directory ein Flag oder man muss zuerst auf das entsprechende INode zugreifen und dort schauen, was es ist.
Aber als Fazit bleibt zu sagen, dass 'ExamineDirectory()' nicht der schnellste Weg ist, weil es mehr Informationen abfragt als du eigentlich brauchst.
Alle Dateien ohne Unterverzeichnisse finde ich in Linux mittels folgendem Konsolenbefehl:
In meinem Thumbnail-Verzeichnis kriege ich so nach 50 ms das Ergebnis 10544 Dateien.
Hier findest du noch ein paar praktische DOS-Programme, die es für Unix schon länger gibt. Aber ich glaube das ist sinnfrei. Schau dir unter Windows lieber mal die API an.
Re: Schnelles Zählen von Dateien
Verfasst: 22.11.2010 17:20
von Rings
Windows only und nicht rekursiv:
Code: Alles auswählen
Procedure CountFiles(sPath.s)
f.WIN32_FIND_DATA
hFile.l
NumFiles.l = 0
If Right(sPath, 1) <> "\" :sPath = sPath + "\":EndIf
sPath = sPath + "*.*"
;start a file enum in the specified path
hFile = FindFirstFile_(sPath, f)
If hFile = #INVALID_HANDLE_VALUE
ProcedureReturn 0
EndIf
;Exclude subdirectories from count
If (f\dwFileAttributes And #FILE_ATTRIBUTE_DIRECTORY) = 0
NumFiles = 1
EndIf
While FindNextFile_(hFile, f)
If (f\dwFileAttributes & #FILE_ATTRIBUTE_DIRECTORY) = 0
NumFiles +1
Else
;it is a directory, recursive here ?
EndIf
Wend
;Close the file search
FindClose_(hFile)
ProcedureReturn NumFiles
EndProcedure
Debug CountFiles("C:\windows\system32")
Debug CountFiles("C:\Gibtesnet")
Re: Schnelles Zählen von Dateien
Verfasst: 22.11.2010 17:22
von PureLust
NicTheQuick hat geschrieben:In meinem Thumbnail-Verzeichnis kriege ich so nach 50 ms das Ergebnis 10544 Dateien.

10.544 Verzeichniseinträge in 50ms ... davon kann man unter Windows leider nur träumen.
Einer der großen Vorteile der meisten Linux-Dataisysteme ist nun mal die Art, wie dort die Verzeichnisstrukturen abgelegt sind.
Bei den meisten Linux-Dateisystemen liegen (zumindest meines Wissens nach) die Verzeichniseinträge seriell hintereinander.
Somit kann man die Dateiliste eines Verzeichnisses auf einen Rutsch einlesen.
Unter NTFS sieht das leider ganz anders aus. Hier hast Du so eine Art Linked-List, in der ein Eintrag auf den nächsten verweist und dieser wiederum auf den nächsten, wobei die einzelnen Einträge weit voneinander entfernt liegen können.
Bei NTFS musst Du also jeden Eintrag einzeln lesen und der Schreib-/Lesekopf der Festplatte im schlimmsten Fall für jeden Eintrag neu positioniert werden.
Somit wird man es also selbst bei einem lokalen NTFS-Datenträger wohl niemals schaffen 10.000 Verzeichniseinträge in 50ms auszulesen.
Bei einem Netzlaufwerk (um das es MK_2007 ja ging) kommen dann noch die Netzwerk-Latenzen für jede neue Anfrage hinzu.
Ich werde gleich aber mal zu Testzwecken auf zwei unserer Netzlaufwerke ~10.000 Dateien anlegen und schauen wie schnell ein "Dir /w" im Vergleich zur geposteten "CountFiles()" Routine ist.
Zum einen werde ich das mal auf einem RAID10-Verbund aus "normalen" Server-Platten und zum Anderen auf SSDs testen. Bin mal gespannt, ob man hier einen Unterschied feststellen kann, oder ob der Vorteil der SSD durch die Netzwerklatenzen komplett geschluckt wird.
Re: Schnelles Zählen von Dateien
Verfasst: 23.11.2010 14:35
von MK_2007
Schon mal vielen Dank an alle Schreiber...!
Ich benötige die Routine um aus einem Programm heraus Verzeichnisse zu überwachen und die Anzahl der Dateien anzuzeigen.
Die Vereichnisdaten werden alle 15 Sekunden aktualisiert.
Habe das Listing von Rings probiert... ist leider auch zu langsam. Bei mir braucht es für 4000 Dateien knapp 20 Sekunden.
Wenn ich mit Windows auf das Laufwerk zugreife und mir die Dateien anzeigen lasse, dauert es knapp 3 Sekunden. Kennt sich jemand vielleicht mit API's aus? Vielleicht geht es damit schneller.
Vorab schon mal vielen Dank.
Re: Schnelles Zählen von Dateien
Verfasst: 23.11.2010 14:49
von PureLust
Sorry ... bin leider gestern nicht mehr dazu gekommen, hier die Testdateien anzulegen und die Tests zu machen.
MK_2007 hat geschrieben:Wenn ich mit Windows auf das Laufwerk zugreife und mir die Dateien anzeigen lasse, dauert es knapp 3 Sekunden. Kennt sich jemand vielleicht mit API's aus? Vielleicht geht es damit schneller.
Wenn Dir Windows so schnell die Dateien liefert, dann mach's doch, wie Blackskyliner bereits gesagt hat:
- Dir %Pfad% /w >C:\Dateiliste.txt
Dann kannst Du in der vorletzten Zeile von "C:\Dateiliste.txt" einfach die Anzahl der Dateien auslesen.
Wenn's Dir allerdings einfach nur darum gehen sollte, ein Verzeichnis auf Veränderungen zu überprüfen (also ohne die Dateien zu zählen), so gibt's dafür 'ne einfache und schnelle Lösung per API.
Re: Schnelles Zählen von Dateien
Verfasst: 23.11.2010 15:18
von Rings
MK_2007 hat geschrieben:
Habe das Listing von Rings probiert... ist leider auch zu langsam. Bei mir braucht es für 4000 Dateien knapp 20 Sekunden.
Wenn ich mit Windows auf das Laufwerk zugreife und mir die Dateien anzeigen lasse, dauert es knapp 3 Sekunden. Kennt sich jemand vielleicht mit API's aus? Vielleicht geht es damit schneller.
Vorab schon mal vielen Dank.
Ich hab hier 78 msec für gute 3500 Dateien.
kann es sein das dein virenscanner dich ausbremst ?
Debugger an ?
Re: Schnelles Zählen von Dateien
Verfasst: 23.11.2010 17:21
von edel
@Rings
Es kommt noch auf die Platte an, ein Ordner mit 10001 Dateien kann ich hier nichtmal mehr messen, system32 mit 2800irgendwas genauso wenig. Der Code ist also durchaus brauchbar.
Die Windowsvariante von NicTheQuick Konsolenbefehl sollte ungefaehr so gehen :