Seite 1 von 3

FindFile

Verfasst: 13.11.2007 23:23
von mpz
Hallo Leute,

habe das FindFile aus dem englischen Forum auf Purebasic 4.10 Beta 4 angepasst. Wenn ich Zeit habe erweitere ich es um "Wildcards"...

Gruß Michael

Code: Alles auswählen


;-TOP 
; Kommentar : Eine einzelne Datei wird gesucht
;
; Version   : v1.00 
; Author    : by blueznl 15/Nov/2003 and by DiGe 03/Feb/2005 
;             Anpassung an 4.10 beta4 by Michael Paulwitz
;              
; Datei     : Findfile.pb 
; Erstellt  : 9.11.2007 
; Sprache   : Purebasic 4.10 Beta 4 Windows
; *************************************************************************************** 



Procedure.s FindFile(Dir.s,file.s) 
   Protected ID.l, files.s 

   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 
               If UCase(DirectoryEntryName(ID)) = UCase(file.s)
                  ProcedureReturn Dir + DirectoryEntryName(ID)
                  Break
               EndIf
            Case #PB_DirectoryEntry_Directory
               If DirectoryEntryName(ID) <> "." And DirectoryEntryName(ID) <> ".." 
                  files.s = FindFile(Dir + DirectoryEntryName(ID),file.s) 
                  If files.s
                    Break
                  EndIf  
               EndIf 
         EndSelect 
      Wend 
      FinishDirectory(ID)
   EndIf 
   ProcedureReturn files.s 
EndProcedure 

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

If Dir
   Dateisuchen.s = "explorer.exe"
   Datei.s = FindFile(Dir,Dateisuchen)
   If Datei
      MessageRequester(Dir, "Die Datei <" + Datei + "> wurde gefunden")
   Else
      MessageRequester(Dir, "Die Datei <" + Dateisuchen + "> wurde nicht gefunden")
   EndIf 
EndIf
End


Verfasst: 14.11.2007 00:24
von AND51
// Edit: Verweisen möchte ich auf Seite 2 dieses Threads - dort gibt es noch besere Prozeduren, die auch Callbacks und das Suchen mehrerer Dateien auf einmal unterstützen.



Hier habe ich deine Version sehr stark verbessert:

Code: Alles auswählen

; AND51
; Nov-2007
; For free use, credits appreciated

Procedure.s FindFile(file.s, directory.s, recursive=1)
	PathAddBackslash_(@directory)
	Protected result.s, dir=ExamineDirectory(#PB_Any, directory, file)
	If dir And NextDirectoryEntry(dir)
		result=directory+DirectoryEntryName(dir)
		FinishDirectory(dir)
	ElseIf recursive
		dir=ExamineDirectory(#PB_Any, directory, "")
		If dir
			While NextDirectoryEntry(dir) And Not result
				If DirectoryEntryType(dir) = #PB_DirectoryEntry_Directory And DirectoryEntryName(dir) <> "." And DirectoryEntryName(dir) <> ".."
					result=FindFile(file, directory+DirectoryEntryName(dir), 1)
				EndIf
			Wend
			FinishDirectory(dir)
		EndIf
	EndIf
	ProcedureReturn result
EndProcedure


Debug FindFile("hiberfil.sys", "C:", 1)
  • Edit: Code leicht nachgebessert
  • Case-In-Sensivity, groß-/kleinschreibung egal
  • Wildcards können hemmungslos benutzt werden
  • Rekursive suche kann per Flag an- oder abgeschaltet werden
  • Intelligente Suche: Erst wird die Datei im aktuellen Verzeichnis gesucht, bevor rekursiv die nächsten Ordner durchsucht werden, spart Zeit

Dein Code geht rekursiv sofort in einen Ordner rein, wenn er einen gefunden hat. Dies führt dazu, dass zum Beispiel erst "Dokumente und Einstellungen" durchsucht wird, wenn du nach der Datei "pagefile.sys" suchst, da ExamineDirectory() meistens die Dateien alphabetisch zurückgibt. Dies spart sehr viel Zeit.


Du hast übrigens ein Speicherleck in deinem Code:
mpz hat geschrieben:

Code: Alles auswählen

               If UCase(DirectoryEntryName(ID)) = UCase(file.s) 
                  ProcedureReturn Dir + DirectoryEntryName(ID) 
                  Break 
               EndIf 
Was nützt dir dein Break, wenn du es erst nach ProcedureReturn einsetzt? Und warum verlässt du an dieser Stelle sofort die Prozedur? SO kannst du das Verzeichnis zum Schluss nicht mehr mit FinishDirectory() freigeben ( -> Speicherleck)!

Verfasst: 14.11.2007 01:20
von Kiffi
AND51 hat geschrieben:Hier habe ich deine Version sehr stark verbessert
[hust] das staubt heute mal wieder... ;-)

Grüße ... Kiffi

Verfasst: 14.11.2007 11:19
von AND51
Kiffi hat geschrieben:[hust] das staubt heute mal wieder... ;-)
Ja, ich weiß auch nicht, woher das kommt... Vielleicht liegts an der Brille, musst du deine Brille auch mal wieder reinigen? 8)
Aber mal im Ernst: Die Idee, das Pattern-Parameter bei ExamineDiretory() zu mussbrauchen ist doch raffiniert, oder?


// Edit:
Von meinem Code sollte das Sternchen bei ExamineDirectory() (3. Parameter) entfernt werden, da sonst "Purebasic.exe" gefunden wird, obwohl man vielleicht nur nach "basic.exe" sucht.
Trotzdem können weiterhin munter Wildcards benutzt werden.

Verfasst: 14.11.2007 11:46
von AND51
Teil 2: FindMultipleFiles() - Findet mehr als nur die 1. Datei

Code: Alles auswählen

; AND51
; Nov-2007
; For free use, credits appreciated

EnableExplicit

Procedure FindMultipleFiles(file.s, directory.s, ResultList.s(), recursive=1)
	PathAddBackslash_(@directory)
	Protected dir=ExamineDirectory(#PB_Any, directory, file)
	If dir
		While NextDirectoryEntry(dir)
			AddElement(ResultList())
				ResultList()=directory+DirectoryEntryName(dir)
		Wend
		FinishDirectory(dir)
	EndIf
	If recursive
		dir=ExamineDirectory(#PB_Any, directory, "")
		If dir
			While NextDirectoryEntry(dir)
				If DirectoryEntryType(dir) = #PB_DirectoryEntry_Directory And DirectoryEntryName(dir) <> "." And DirectoryEntryName(dir) <> ".."
					FindMultipleFiles(file, directory+DirectoryEntryName(dir), ResultList(), 1)
				EndIf
			Wend
			FinishDirectory(dir)
		EndIf
	EndIf
	ProcedureReturn CountList(ResultList())
EndProcedure

NewList suche.s()

Debug FindMultipleFIles("*.sys", "C:", suche(), 1)
ForEach suche()
	Debug suche()
Next
Kiffi, basierend auf den exzellenten Vorteilen meines ersten Codes (staubt's immernoch? :mrgreen: )
habe ich den Code erweitert. Er findet nun ALLE Dateien, die auf die angegeben Parametern basieren und speichert die Ergebnisse bequem in die LinkedList, die man übergibt.
Außerdem wird am Schluss noch die Anzahl gefundener Dateien zurückgegeben (ProcedureReturn).

Das Tolle: Bei mir ist der Code selbst mit Debugger so schnell, dass es höchstens 1-3 Sekunden dauert, bis er mein Laufwerk C: komplett/rekursiv nach allen SYS-Dateien durchsucht hat (Ein Kontrolldurchlauf mit allen HTM-Dateien war ebenfalls so schnell). Oder ist diese Schnelligkeit nur bei mir so?

Verfasst: 14.11.2007 11:57
von Thorium
AND51 hat geschrieben: Das Tolle: Bei mir ist der Code selbst mit Debugger so schnell, dass es höchstens 1-3 Sekunden dauert, bis er mein Laufwerk C: komplett/rekursiv nach allen SYS-Dateien durchsucht hat (Ein Kontrolldurchlauf mit allen HTM-Dateien war ebenfalls so schnell). Oder ist diese Schnelligkeit nur bei mir so?
Das währe wirklich aussergewöhnlich schnell, das muss ich mal bei mir ausprobieren.

Verfasst: 14.11.2007 12:06
von Bisonte
dass es höchstens 1-3 Sekunden dauert,
Wenn Du minuten drauss machst, kommen wir ins Geschäft (565 Files gefunden ;)

Ansonsten hätt ich die Platte auch gerne :D

*Sry for Spam

Verfasst: 14.11.2007 12:11
von NicTheQuick
Die Geschwindigkeit hängt mit der Laufzeitindizierung der Festplatte
zusammen.

Versucht mal folgendes:
PC neustarten und Code ausführen. -> Dauert lange.
Code direkt danach nochmal ausführen. -> Geht sehr schnell.
Grund: Alle Verzeichnisinhalte wurden von Windows zwischengespeichert,
damit es beim nächsten Mal eben schneller geht.

Verfasst: 14.11.2007 12:12
von Bisonte
jetzt wo du das erwähnst ... stimmt... weniger als 2 Sekunden ... alle achtung.

Hätt ich auch selbst drauf kommen können ;)

Verfasst: 14.11.2007 12:16
von Thorium
Jopp ist bei mir ungefähr gleich schnell wie die Windows-Suche.