Existiert eine Datei oder ein Ordner?
von Herfried K. Wagner
Einleitung
In dieser Ausgabe wollen wir verschiedene Möglichkeiten betrachten, mit denen man feststellen kann, ob eine Datei oder ein Ordner auf dem System existiert. Für diesen Zweck existieren in der Funktionsbibliothek von Visual Basic leider keine eigenen Funktionen. Deshalb muss eine Lösung auf anderem Wege gesucht werden. Die vorgestellten Möglichkeiten zur Existenzprüfung dienen nicht dazu, festzustellen, ob auf eine Datei oder einen Ordner zugegriffen werden kann, sondern können lediglich dazu benutzt werden, zu überprüfen, ob eine Datei oder ein Ordner existiert.
Neben den vorgestellten Methoden gibt es noch eine Menge anderer Möglichkeiten. Weitere Informationen zu diesem Thema finden sich im entsprechenden Artikel von Jost Schwider. An dieser Stelle sei Jost Schwider für wichtige Hinweise, die in diesen Artikel Eingang gefunden haben, gedankt. Die Kolumne wurde am 1. November 2005 auf Basis von Kommentaren ergänzt und überarbeitet.
Existenzprüfung mit Visual Basic-eigenen Funktionen
Folgende Funktion prüft mit Visual Basic-eigenen Mitteln, ob eine Datei oder ein Ordner existiert. Dazu wird die Funktion GetAttr benutzt, die dazu dient, Attribute einer Datei oder eines Ordners zu ermitteln. Wird diese Funktion auf einen nicht existierenden Pfad angewendet, so wird ein Fehler ausgelöst. Durch On Error Resume Next wird unterbunden, dass die Anwendung mit einem Fehler beendet wird.
Private Function FileExists(ByVal FileName As String) As Boolean On Error Resume Next FileExists = Not CBool(GetAttr(FileName) And (vbDirectory Or vbVolume)) On Error Goto 0 End Function Private Function DirExists(ByVal DirectoryName As String) As Boolean On Error Resume Next DirExists = CBool(GetAttr(DirectoryName) And vbDirectory) On Error Goto 0 End Function
Anstelle von GetAttr im obigen Beispiel könnte auch bspw. die Funktion FileLen oder eine passende andere Dateizugriffsfunktion benutzt werden. Auf die Verwendung der Funktion Dir$ zur Existenzprüfung sollte aber dringend verzichtet werden, da diese Funktion nicht eintrittsinvariant ist. Ihre Verwendung kann zur Folge haben, dass sich anderen Programmteile nach Aufruf der Funktion zur Existenzprüfung nicht mehr wie erwartet verhalten. Im folgenden Beispiel wird in der Prozedur EnumDirs Dir$ zur Aufzählung der Unterordner eines Ordners verwendet. Wird während der Aufzählung eine auf Dir$ basierende Funktion zur Existenzprüfung eingesetzt (im Listing markiert durch ein Rufzeichen), führt dies zu unvollständigen Aufzählungsergebnissen.
Private Sub EnumDirs(ByVal Path As String) Dim CurrentDir As String CurrentDir = Dir$(Path, vbDirectory) Do While Len(CurrentDir) > 0 If CurrentDir <> "." And CurrentDir <> ".." Then If _ CBool(GetAttr(CombinePath(Path, CurrentDir)) And vbDirectory) _ Then Debug.Print CurrentDir End If End If Debug.Print DirExists("C:\Programme") ' ! CurrentDir = Dir$ Loop End Sub Private Function DirExists(ByVal Path As String) As Boolean DirExists = (Len(Dir$(Path, vbDirectory)) > 0) End Function Private Function CombinePath(ByVal Part1 As String, ByVal Part2 As String) CombinePath = Part1 If Right$(CombinePath, 1) <> "\" Then CombinePath = CombinePath & "\" End If CombinePath = CombinePath & Part2 End Function
Existenzprüfung mit dem FileSystemObject
Das FileSystemObject stellt eine Methode mit dem Namen FileExists bereit, die benutzt werden kann, um die Existenz einer Datei zu ermitteln. Analog dazu besitzt das Objekt eine Methode FolderExists zur Existenzbestimmung von Ordnern. Alleine zur Überprüfung der Existenz einer Datei oder eines Ordners ist das FileSystemObject jedoch überdimensioniert und das Hinzufügen der Abhängigkeit zu einem Projekt nicht gerechtfertigt. In Projekten, in denen ohnehin bereits Gebrauch von dieser Komponente gemacht wird, erweist sich diese Methode hingegen als nützlich.
Existenzprüfung mit API-Aufrufen
Eine einfache Methode zur Existenzüberprüfung von Dateien und Ordnern stellt die Verwendung der API-Funktion GetFileAttributes dar, die ähnlich der Visual Basic-eigenen Funktion GetAttr zum Lesen von Dateiattributen dient. Anders als bei der Funktion GetAttr kann jedoch die Fehlerbehandlung zugunsten der Überprüfung des Rückgabewerts der Funktion eingespart werden.
Private Declare Function GetFileAttributes _ Lib "kernel32.dll" _ Alias "GetFileAttributesA" _ ( _ ByVal lpFileName As String _ ) As Long Private Const INVALID_FILE_ATTRIBUTES As Long = -1& Private Const FILE_ATTRIBUTE_DIRECTORY As Long = &H10& Private Function FileExists(ByVal FileName As String) As Boolean Dim dwAttributes As Long dwAttributes = GetFileAttributes(FileName) If dwAttributes = INVALID_FILE_ATTRIBUTES Then FileExists = False ElseIf CBool(dwAttributes And FILE_ATTRIBUTE_DIRECTORY) Then FileExists = False Else FileExists = True End If End Function Private Function DirExists(ByVal DirectoryName As String) As Boolean Dim dwAttributes As Long dwAttributes = GetFileAttributes(DirectoryName) If dwAttributes = INVALID_FILE_ATTRIBUTES Then DirExists = False ElseIf CBool(dwAttributes And FILE_ATTRIBUTE_DIRECTORY) Then DirExists = True Else DirExists = False End If End Function
Eine weitere Lösung, die auf der Windows-API basiert, macht sich die Funktionen FindFirstFile und FindClose zunutze. Über die erste Funktion erhält man eine Zugriffsnummer auf die erste Datei, deren Name dem übergebenen Muster entspricht. Wenn die Zugriffsnummer gleich -1 ist, dann konnte die Datei nicht gefunden werden. Abschließend wird der Suchvorgang beendet.
Private Declare Function FindFirstFile _ Lib "kernel32.dll" _ Alias "FindFirstFileA" _ ( _ ByVal lpFileName As String, _ ByRef lpFindFileData As WIN32_FIND_DATA _ ) As Long Private Declare Function FindClose Lib "kernel32.dll" ( _ ByVal hFindFile As Long _ ) As Long Private Const INVALID_HANDLE_VALUE As Long = -1& Private Const MAX_PATH As Long = 260& Private Type FILETIME dwLowDateTime As Long dwHighDateTime As Long End Type Private Type WIN32_FIND_DATA dwFileAttributes As Long ftCreationTime As FILETIME ftLastAccessTime As FILETIME ftLastWriteTime As FILETIME nFileSizeHigh As Long nFileSizeLow As Long dwReserved0 As Long dwReserved1 As Long cFileName As String * MAX_PATH cAlternate As String * 14 End Type Private Function FileExists(ByVal FileName As String) As Boolean Dim wfd As WIN32_FIND_DATA Dim hFile As Long hFile = FindFirstFile(FileName, wfd) FileExists = (hFile <> INVALID_HANDLE_VALUE) If hFile <> INVALID_HANDLE_VALUE Then Call FindClose(hFile) End If End Function
Weiters bietet sich die API-Funktion PathFileExists aus der shlwapi.dll an. Ein Beispiel zu deren Verwendung findet sich im Tipp 0605: Path-APIs nutzen. Es ist zu beachten, dass diese Funktion nicht unter allen Versionen von Windows zur Verfügung steht.
Ihre Meinung
Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.
Archivierte Nutzerkommentare
Klicken Sie diesen Text an, wenn Sie die 19 archivierten Kommentare ansehen möchten.
Diese stammen noch von der Zeit, als es noch keine direkte Forenunterstützung für Fragen und Kommentare zu einzelnen Artikeln gab.
Aus Gründen der Vollständigkeit können Sie sich die ausgeblendeten Kommentare zu diesem Artikel aber gerne weiterhin ansehen.
Kommentar von XETH am 02.01.2008 um 13:40
On Local Error Resume Next macht seit vb6 keinen unterschied mehr zur variante
Kommentar von Codefreaker am 25.02.2007 um 10:49
So spart man noch je eine Zeile.
Besser:
Private Function FileExists(ByVal FileName As String) As Boolean
On Local Error Resume Next
FileExists = Not CBool(GetAttr(FileName) And (vbDirectory Or vbVolume))
End Function
Private Function DirExists(ByVal DirectoryName As String) As Boolean
On Local Error Resume Next
DirExists = CBool(GetAttr(DirectoryName) And vbDirectory)
End Function
Kommentar von Tio am 28.09.2006 um 15:24
Hey, Super, funktioniert!! Danke Philipp!
Kommentar von Philipp Stephani am 28.09.2006 um 14:49
@Tio: Dafür musst du FindFirstFile benutzen, siehe Listing 4.
Kommentar von Tio am 28.09.2006 um 14:29
Hallo,
wie ist es möglich, dass ich dem Dateinamen ein Asteriks mitgeben kann? Es geht darum, dass ich z.B. eine Datei ABC22.pdf habe, wobei ich nur auf "ABC*.pdf" prüfen will (anstelle der "22" können mehrere Zeichen folgen). Ich habe mal probehalber [Verzeichnis]\ABC*.pdf an die Funktion FileExists übergeben, aber trotz definitivem Vorhandenseins wurde sie nicht gefunden. Also geht das mit dem "*" nicht. Wie kann man das hinkriegen? Gibt es da eine andere Funktion für?
Kommentar von Philipp Stephani am 13.09.2006 um 00:09
@d1ng0d0gt0r: Wird in der Kolumne bereits behandelt (Abschnitt «Existenzprüfung mit dem FileSystemObject»).
Kommentar von d1ng0d0gt0r am 12.09.2006 um 22:08
Ich hab hier eine einfachere Funktion gefunden zum überprüfen von Dateien:
private sub command1_click()
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists("C:\test.txt") Then
msgbox "exist"
else
msgbox "not exist"
end if
end sub
Kommentar von d1ng0d0gt0r am 12.09.2006 um 22:03
Kann mir jemand sagen wie ich das anwende?
Kommentar von P. Walther am 06.07.2006 um 13:08
Ich finde das Forum einfach super,
war mir bisher eine große Hilfe.
Paul
Kommentar von S. Beil am 03.07.2006 um 18:55
Tolle und fundierte Hilfe!
Ist leider selten im Internet geworden.....
Kommentar von oest am 16.03.2006 um 13:04
Einfach toll.
Solche essentiellen Beiträge wünscht man sich.
Kommentar von Florian Rittmeier am 05.11.2005 um 08:42
Die bisher geposteten Beiträge wurde von Herfried K. Wagner in den Artikel eingearbeitet.
Gruß Florian
-------------------
Team ActiveVB
Kommentar von am 19.07.2005 um 21:20
@Sebastian:
Die Methode heißt "FolderExists".
Kommentar von Sebastian am 19.07.2005 um 15:50
Private Function ExistFolder(ByRef strPath As String) As Boolean
Dim objFSO As Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
ExistFolder = objFSO.DirExists(strPath)
End Function
----------
Das FileSystemObject hat überhaupt
keine Methode namens DirExists !!!
Lediglich DriveExists.
Kommentar von Timon am 01.02.2005 um 10:05
"PathFileExist" ist auch eine gute möglichkeit!
im tipp0605 werden "PathFileExist" und noch viele andere API's für die arbeit mit pfaden erklärt.
(http://www.activevb.de/tipps/vb6tipps/tipp0605.html)
Gruss Timon
Kommentar von Jan-Marten am 07.01.2005 um 05:34
Kann man das nich auch einfach mit dem "PathFileExists" API machen??? oder arbeitet das irgentwie schlechter oder langsamer?
Hat mich nur gewundert, dass diese Lösung hier nicht gelistet ist.
mfg. Jan-Marten
Kommentar von Philipp am 11.12.2003 um 11:30
Die Existenz einer Datei kann auch leichter mittels API geprüft werden:
Declare Function PathFileExists Lib "shlwapi.dll" Alias "PathFileExistsA" (ByVal pszPath As String) As Long
Philipp
Kommentar von Recable am 16.09.2003 um 19:51
Ich finde die Kolumne sollte auch auf der Hauptpage verlinkt werden. Dieser Beitrag hat mir sehr gefallen
Kommentar von Philipp Stephani am 17.04.2003 um 20:33
Das Buch "Visual Basic Hardcore" (in der MSDN Library enthalten) bietet die API-Funktion GetFileAttributes an, die ebenfalls keinen Fehlerauslöst und einfacher als die FindFirstFile-Funktion ist.