Ü vbg.vbnet.beginner | Omgaan met files en directories binnen Visual Basic .NET |
In Visual Basic 6 was het werken met bestanden en mappen niet altijd even vriendelijk. Met de komst van het FileSystemObject binnen de Microsoft Scripting Runtime library werd het al veel beter. Het .NET Framework biedt je gelukkig een aantal classes waarmee het manipuleren van bestanden en mappen een stuk eenvoudiger is geworden. Deze classes bevinden zich in de System.IO namespace.
De classes die we eens nader gaan bekijken zijn: Directory, File, Path, DirectoryInfo en FileInfo. De eerste drie zijn zogenaamde static classes met shared methods. Simpel gezegd komt het erop neer dat u deze classes niet als eigen objectvariabele hoeft te instantiëren. • Directory. Deze class bevat methodes waarmee je bestandsmappen kunt doorlopen en manipuleren; • DirectoryInfo. Een objectinstantie van deze class representeert een individuele bestandsmap en bevat methodes om de attributen te bepalen of te manipuleren; • File. Deze class bevat methodes waarmee je bestanden kunt doorlopen en manipuleren; • Path. Deze class bevat methodes waarmee je padinformatie kunt extraheren en manipuleren; • FileInfo. Een objectinstantie van deze class representeert een individueel bestand en bevat methodes om de attributen te bepalen of te manipuleren. De Directory- en File-classes hebben veel van elkaar weg, een groot aantal methods komen dan ook overeen. In sommige gevallen retourneren deze methods objecten van het type DirectoryInfo en FileInfo.
Directory-class Met behulp van deze class kun je directories manipuleren of er simpelweg informatie over opvragen. Hoewel de onderstaande lijst met methods niet volledige is, geeft het wel een goed beeld van de mogelijkheden. CreateDirectory(path) Delete(path[, recursive])
Exists(path) GetCreationTime(path) GetLastAccessTime(path) GetLastWriteTime(path) SetCreationTime(path) SetLastAccessTime(path) SetLastWriteTime(path) GetCurrentDirectory() GetFiles(path[,filespec])
Maakt de directory (en eventueel alle andere directories in de path) aan. Verwijdert een directory. Optioneel kunt u aangeven of ook eventuele subdirectories en bestanden verwijderd moeten worden. Geeft True terug indien de directory bestaat. Retourneert de tijd (of stelt deze in) waarop de directory gemaakt is, laatste keer benadert is en de laatste keer waneer er in die map iets gewijzigd is.
GetLogicalDrives() GetParent(path) Move(source, dest)
neel gefilterd op bepaalde criteria. Retourneert een String-array met alle logische stations op het systeem. Retourneert de parentdirectory als een DirectoryInfo-object. Verplaatst een directory.
De beste manier om bepaalde objecten en technieken in de vingers te krijgen is in de meeste gevallen het maken van een voorbeeldproject. Voor gevallen waarbij er geen userinterface-objecten benodigd zijn, gaat mijn voorkeur uit naar een Console-application. U kunt heel snel aan de slag en het compileren gaat ook veel sneller. Daarnaast kan men zich ook erg goed richten op de daadwerkelijke functionaliteit. Ik denk dat de commentaarregels in het onderstaande voorbeeld u voldoende houvast zullen geven om de werking te kunnen begrijpen. Vergeet niet dat de namespace System.IO geimporteerd moet zijn! Listing 1 | Test de DirectoryClass Private Sub TestDirectoryClass() ' Bepaal huidige folder Console.WriteLine("Print huidige directory") Console.WriteLine(Directory.GetCurrentDirectory) Console.ReadLine() ' wachten op toets ' Maak een folder aan Console.WriteLine("Maak folder 'C:\VBG\Test' aan") Directory.CreateDirectory("C:\VBG\Test") Console.ReadLine() ' wachten op toets ' Toon CreateTime voor aangemaakte folder Console.WriteLine("Aanmaaktijd 'C:\VBG\Test' is") Console.WriteLine(Directory.GetCreationTime("C:\VBG\Test")) Console.ReadLine() ' wachten op toets ' Bepaal alle DLL in de system 32 map die beginnen met ex.. Dim strFiles() As String Dim intCounter As Int32 ' Bepaal de DLL’s in de System32 map die beginnen met ‘ex’ strFiles = Directory.GetFiles("c:\windows\system32", _ "ex*.dll") For intCounter = 0 To strFiles.Length - 1 Console.WriteLine(strFiles(intCounter)) Next Console.ReadLine() ' wachten op toets
Retourneert de huidige directory. Retourneert een String-array met alle bestanden in de opgegeven map, optio-
| VB Magazine Online | 2004 – 12 |
End Sub
1/5
Ü vbg.vbnet.beginner | Omgaan met files en directories binnen Visual Basic .NET |
De code in Listing 1 resulteert in het volgende resultaat:
Afbeelding 2 | Test de DirectoryInfo-class
Afbeelding 1 | Test de Directory-class
Wanneer u een map probeert aan te maken die al bestaat, dan wordt de opdracht genegeerd. De map wordt niet verwijdert en opnieuw aangemaakt. Ook zal er geen exception optreden. De method Delete() genereert een exception indien u een map probeert te verwijderen waarin zich bestanden of subdirectories bevinden. U kunt dit omzeilen door als tweede parameter ‘True’ mee te geven. Hierdoor wordt de map volledig verwijderd.
DirectoryInfo-class Qua functionaliteit lijken de classes Directory en DirectoryInfo erg sterk op elkaar. Zoals reeds eerder gezegd is de DirectoryInfo class en instance-class, wat inhoudt dat u het moet instantiëren en moet toekennen aan een variabele. Deze class representeert een individuele directory en is afgeleid van de FileSystemInfo-class. Hierdoor hebben DirectoryInfo en FileInfo ook veel methods en properties gemeen, omdat ook FileInfo hiervan afgeleid is. Hoewel het lijkt dat het gebruik van deze class ingewikkelder is, is dat slechts deels waar. Inderdaad, je kunt het niet zomaar aanroepen, maar het gebruik is erg eenvoudig. In Listing 2 ziet u een aantal mogelijkheden. Listing 2 | Test de DirectoryInfo-class Private Sub TestDirectoryInfoClass()
Dim objDI As New DirectoryInfo("C:\VBG\Test") ' Bepaal of folder bestaat If objDI.Exists = True Then Console.WriteLine("Gemaakt op:" & objDI.CreationTime) Console.ReadLine() ' wachten op toets Else ' Folder bestaat niet... maak het aan objDI.Create() Console.WriteLine("Gemaakt op:" & objDI.CreationTime) Console.ReadLine() ' wachten op toets End If ' Toon alle mappen in c:\inetpub Dim objDL As New DirectoryInfo("c:\inetpub") Dim objD As DirectoryInfo Console.WriteLine("Alle folders in C:\Inetpub") ' Doorloop alle mappen en toon Naam + Datum For Each objD In objDL.GetDirectories() Console.WriteLine(objD.Name & " - " & objD.CreationTime) Next Console.ReadLine() ' wachten op toets End Sub
| VB Magazine Online | 2004 – 12 |
Doordat de DirectoryInfo class een individuele map vertegenwoordigt, kan men ook properties instellen. Zoals u het mag verwachten, krijgt u hulp van Intellisense. In afbeelding 3 ziet u hoe u een directory op ‘alleen lezen’ kunt instellen. De directory die u hebt aangegeven in de constructor hoeft niet te bestaan. U kunt het object immers ook gebruiken om de directory aan te maken. Vergeet in dit geval niet om met behulp van de Refresh() method uw object te dwingen de gewijzigde properties opnieuw in te lezen.
Afbeelding 3 | Instellen property op DirectoryInfo object
In Listing 2 heeft u kennis gemaakt met een aantal properties en methods. Ik zet de meest handige voor u op een rij. Attributes Create CreationTime CreateSubDirectory(path)
Delete([recursive])
GetDirectories([filespec])
GetFiles([filespec])
LastAccessTime LastWriteTime
MoveTo(destpath) Parent Refresh Root
Retourneert de attributen van deze directory of stelt deze in. Maakt de opgegeven directory. Retourneert de tijd waarop deze directory is aangemaakt. Maakt de opgegeven subdirectory en retourneert deze als DirectoryInfo object. Verwijdert een directory. Optioneel kunt u aangeven of ook eventuele subdirectories en bestanden verwijdert moeten worden. Retourneert een array van DirectoryInfo objecten met de subdirectories van de opgegeven directory. Optioneel kunt u nog een filter opgeven. Retourneert een array van FileInfo objecten met alle bestanden in de opgegeven directory. Optioneel kunt u nog een filter opgeven. Retourneert de tijd waarop de directory voor het laatst benaderd is. Retourneert de tijd waarop de inhoud van de directory voor het laatst gewijzigd is. Verplaatst de directory naar de opgegeven locatie. Retourneert een DirectoryInfo object met parent van de opgegeven directory. Ververst de status van het object. Retourneert een DirectoryInfo object met de root van de opgegeven directory.
2/5
Ü vbg.vbnet.beginner | Omgaan met files en directories binnen Visual Basic .NET |
Wanneer u een directory probeert te verplaatsten met behulp van de MoveTo() method, dan mag de doelfolder nog niet bestaan.
File-class Net zoals de Directory- en DirectoryInfo-classes, delen de File- en FileInfo-classes veel properties en methods. En net zoals de Directory-class, kent de File-class alleen shared methods. Wanneer u System.IO geïmporteerd heeft, kunt u de methods van deze class direct aanroepen. In veel gevallen dient u als eerste en vaak enige parameter de bestandsnaam mee te geven. Listing 3 | Test de File-class Private Sub TestFileClass() ' Bepaal of test.txt bestaat.. zoniet dan maken If File.Exists("C:\VBG\Test1.txt") = False Then ' Nee... maak bestand Dim objFS As FileStream = File.Create("C:\VBG\Test1.txt") objFS.Close() ' Toon status Console.WriteLine("Bestand 1 is aangemaakt...") Console.ReadLine() ' wachten op toets End If
FileShare enumerations kunt u namelijk deze bestanden bewerken. Ik ben echter van mening dat wanneer u een FileStream-object wilt creëren u beter de constructor van deze class kunt gebruiken. Indien u het kunt oplossen met behulp van één object, dan heeft dat altijd mijn voorkeur.
Afbeelding 4 | Gebruik FileStream-object
Wanneer u de code goed bekeken hebt, hebt u wellicht gezien dat we in de laatste opdracht de attributen van het bestand hebben ingesteld op ‘Alleen-lezen’ en ‘Archief’. Indien we nu code een tweede maal zouden aanroepen dan krijgen we een exception op de regel waarin we het bestand ‘C:\VBG\Test2.txt’ proberen te verwijderen. We hebben immers dit bestand ingesteld op ‘Alleen-lezen’! U zou deze exception kunnen afvangen of, beter nog, uw code uitbreiden met een extra controle op de attributen.
' Bepaal of bestand in subdirectory bestaat. If File.Exists("C:\VBG\Test2.txt") = True Then ' Ja... verwijder bestand File.Delete("C:\VBG\Test2.txt") ' Toon status Console.WriteLine("Bestand 2 is verwijderd...") Console.ReadLine() ' wachten op toets End If ' Kopieer bestand naar een andere locatie File.Copy("C:\VBG\Test1.txt", "C:\VBG\Test2.txt") ' Toon status Console.WriteLine("Bestand is gekopieerd...") Console.ReadLine() ' wachten op toets ' Stel attributen in File.SetAttributes("C:\VBG\Test2.txt", _ FileAttributes.ReadOnly + _ FileAttributes.Archive) ' Toon status Console.WriteLine("De attributen zijn aangepast...") Console.ReadLine() ' wachten op toets End Sub
In Listing 3 worden een aantal methods van de File-class in praktijk gebracht. U ziet dat de Create() method een FileStream-object retourneert. Er zijn een aantal andere methods op deze class die ook een FileStream-object retourneren. Hierbij kunt u denken aan Open(), OpenRead() of OpenWrite(). Dit FileStream-object kunt vervolgens gebruiken om met behulp van bijvoorbeeld een TextWriter-object in het bestand te gaan schrijven. Afhankelijk van de keuze van waarden voor de FileMode-, FileAccess- en
| VB Magazine Online | 2004 – 12 |
Afbeelding 5 | Test de File-class
FileInfo-class U heeft al kort kennisgemaakt met deze class tijdens de bespreking van de DirectoryInfo-class. Aangezien beide classes zijn afgeleid van de FileSystemInfo-class hebben ze veel dezelfde properties en methods. Vanzelfsprekend hebben deze dan geen betrekking op directories, maar op bestanden. Een aantal methods en properties die overeen komen zijn: • Name • FullName • Extension • Exists • Attributes • CreationTime
3/5
Ü vbg.vbnet.beginner | Omgaan met files en directories binnen Visual Basic .NET |
• • • •
LastWriteTime LastAccessTime Refresh Delete
Info, kun je dan eigenschappen opvragen zoals de bestandsnaam of aanmaakdatum. Het instellen van eigenschappen zoals ‘attributes’ gaan net iets intuïtiever dan met de File-class. Instellen van properties met behulp van Intellisense (zie afbeelding 4) werkt nu eenmaal prettiger.
Daarnaast kent de FileInfo-class ook een aantal methods en properties die specifiek voor dit object zijn. De AppendText(), CreateText(), Open(), OpenRead(), OpenWrite en de OpenText() methods laat ik achterwege omdat voor deze methods ook geldt dat het een FileStream-object retourneert. Zoals reeds gemeld vind ik dat dit soort FileStreams door het betreffende object geïnstantieerd zouden moeten worden. Directory DirectoryName Length Create MoveTo(destpath) CopyTo(destfile[, overwrite]
Retourneert een DirectoryInfo-object die de parent-directory representeert. Retourneert de naam van de parentdirectory. Retourneert de grootte van het bestand. Maakt het bestand aan. Verplaatst het bestand naar een andere directory. Kopieert het bestand naar een andere pad en bestand. Optioneel kunt u aangeven of het doelbestand overschreven dient te worden.
Een object van dit type of een array ervan wordt veelvuldig gebruikt als returnwaarde van bepaalde methods van de DirectoryInfo-class. Listing 4 | Test de FileInfo-class Private Sub TestFileInfoClass() ' C:\Windows is werkdirectory Dim objDI As New DirectoryInfo("C:\Windows") Dim objFI As FileInfo ' Toon alle *.txt in deze directory For Each objFI In objDI.GetFiles("*.txt") ' Toon naam + datum/tijd aanmaak Console.WriteLine(objFI.Name & " - " & objFI.CreationTime) Next Console.ReadLine() ' wachten op toets ' Maak, indien nodig het bestand aan... Dim objFileInfo As New FileInfo("C:\VBG\Test3.txt") If objFileInfo.Exists = False Then objFileInfo.Create() End If ' En markeer het als 'Verborgen' objFileInfo.Attributes = FileAttributes.Hidden objFileInfo.Refresh() ' Toon status Console.WriteLine("Het bestand: " & objFileInfo.Name & _ " bevindt zich in: " & objFileInfo.DirectoryName) Console.ReadLine() ' wachten op toets End Sub
In het bovenstaande voorbeeld ziet u hoe eenvoudig het is om een door een lijst van tekstbestanden te lopen die zich in een bepaalde map bevinden. Voor elke bestand, objFile-
| VB Magazine Online | 2004 – 12 |
Afbeelding 6 | Test de FileInfo-class
Path-class De Path-class kent een aantal shared methods en properties waarmee het werken met bestandsnamen en padnamen sterk vereenvoudigt wordt. Hoewel het op dit moment voor velen onder u nog niet actueel is, bestaat de kans dat we binnen afzienbare tijd ook software gaan ontwikkelen voor andere platformen. De afspraken die gelden voor pad- en bestandsnamen kunnen dan van elkaar afwijken. Hierbij kunt u denken aan scheidingstekens voor directories of tekens binnen een bestandsnaam. Er zijn een aantal properties beschikbaar waarmee dit erg vereenvoudigd wordt: Listing 5 | Test de Path-class - 1 ' Properties voor multiplatform support Console.WriteLine("AltDirectorySeparatorChar - " & _ Path.AltDirectorySeparatorChar) Console.WriteLine("DirectorySeparatorChar - " & _ Path.DirectorySeparatorChar) Console.WriteLine("InvalidPathChars - " & _ Path.InvalidPathChars) Console.WriteLine("PathSeparator - " & _ Path.PathSeparator) Console.WriteLine("VolumeSeparatorChar - " & _ Path.VolumeSeparatorChar) Console.ReadLine() ' wachten op toets
Afbeelding 7 | Multiplatform properties
Naast de ‘multiplatform-properties’ heeft de Path-class ook een aantal methods waarmee men allerlei informatie kan bepalen over paden en bestandsnamen. Ook kunt u met behulp van deze class ook eenvoudig zogenaamde ‘tempory-bestanden’ laten generen. Dit zijn bestanden, met een grootte van nul byte, die u kunt gebruiken om tijdelijk informatie in op te slaan. Na gebruik, bijvoorbeeld tijdens het afsluiten van uw applicatie dient u deze dan weer te verwijderen. In het onderstaande overzicht ga ik uit van de bestandsnaam (path): C:\VBG\Test.txt
4/5
Ü vbg.vbnet.beginner | Omgaan met files en directories binnen Visual Basic .NET |
GetDirectoryName(path)
Retourneert het pad en directory.
GetExtension(path)
Resultaat: C:\VBG Retourneert de extensie van een bestand.
GetFileName(path)
Resultaat: .txt Retourneert de naam en extensie van een bestand.
GetFileNameWithoutExtension(path)
Resultaat: Test.txt Retourneert de bestandsnaam zonder de extensie.
GetFullPath(path)
Resultaat: Test Retourneert het volledige pad van een pad of bestandsnaam.
GetPathRoot(path)
Resultaat: C:\VBG\Test.txt Retourneert de root van het pad of bestandsnaam.
HasExtension(path)
Resultaat: C:\ Retourneert of het pad of bestandsnaam een extensie bevat.
IsPathRootes(path)
Resultaat: True Retourneert of het pad of naam de root bevat.
Ook zijn er, zoals reeds besproken, een tweetal methods om u het werken met tijdelijke bestanden makkelijker te maken.
GetTempPath
Retourneert de unieke bestandsnaam van een bestand met grootte 0. Resultaat bijvoorbeeld: C:\DOCUME~1\OBELIN~1.ACO\ LOCALS~1\Temp\tmpB3.tmp Retourneert het pad van de Temp-map. Resultaat bijvoorbeeld: C:\DOCUME~1\OBELIN~1.ACO\ LOCALS~1\Temp
Het prettige van de deze methods op de Path-class is dat u zich geen zorgen hoeft te maken of het bestand wel of niet bestaat. Het werkt dus ook gewoon met bestanden die niet bestaan. Het is misschien wel goed te vermelden dat de GetFullPath-method een relatief pad omzet naar een absoluut pad, uitgaande van de huidige directory. Listing 6 | Test de Path-class - 2 Dim strFileName As String = "C:\VBG\Test.txt" Console.WriteLine("Path = C:\VBG\Test.txt") Console.WriteLine("GetDirectoryName - " & _ Path.GetDirectoryName(strFileName)) Console.WriteLine("GetExtension - " & _ Path.GetExtension(strFileName)) Console.WriteLine("GetFileName - " & _ Path.GetFileName(strFileName)) Console.WriteLine("GetFileNameWithoutExtension - " & _ Path.GetFileNameWithoutExtension(strFileName))
| VB Magazine Online | 2004 – 12 |
' Tijdelijke bestandnamen Console.WriteLine("GetTempFileName 1 - " & _ Path.GetTempFileName()) Console.WriteLine("GetTempFileName 2 - " & _ Path.GetTempFileName()) Console.WriteLine("GetTempPath - " & _ Path.GetTempPath()) Console.ReadLine() ' wachten op toets
bestands-
Resultaat: True
GetTempFileName()
Console.WriteLine("GetFullPath - " & _ Path.GetFullPath(strFileName)) Console.WriteLine("GetPathRoot - " & _ Path.GetPathRoot(strFileName)) Console.WriteLine("HasExtension - " & _ Path.HasExtension(strFileName)) Console.WriteLine("IsPathRooted - " & _ Path.IsPathRooted(strFileName)) Console.ReadLine() ' wachten op toets
Afbeelding 8 | Diverse methods Path-class
Conclusie De besproken classes maken u het mogelijk om op een eenvoudige en eenduidige wijze code te schrijven. De classes File, Directory en Path zijn static classes; zij kenmerken zich ondermeer, doordat er bijna altijd een variabele als parameter moet worden meegegeven. De shared methods behoren immers tot de class en niet tot de objectinstantie ervan. U kunt het voorbeeldproject downloaden van onze site. Wie is André Obelink? André Obelink (1969) is werkzaam als technical manager en consultant bij AcouSoft Informatisering B.V. AcouSoft is marktleider in Nederland op het gebied van software voor de audicienbranche. Daarnaast bouwt AcouSoft maatwerkapplicaties en ondersteunt zij andere bedrijven bij allerhande softwaretrajecten in VB6/VB.NET/MS Access 97/XP en SQL-Server 7/2000. André is een MCSD, programmeert in Visual Basic sinds 1991 (ja… versie 1.0 dus..) en behoort tot een van de oprichters van de Visual Basic Groep. Als hij niet programmeert, doceert, leest, schrijft of droomt over programmeren, brengt hij graag zijn tijd door met zijn vrouw en twee kinderen. U kunt hem bereiken via
[email protected] © 2004 - Copyright Visual Basic Groep. Dit artikel is auteursrechtelijk beschermd. Afdrukken voor eigen gebruik is toegestaan. http://www.vbgroup.nl
5/5