View Sidebar

A Million Little Pieces Of My Mind

OrganicaLib: FileCrawler Class

By: Paul S. Cilwa Viewed: 5/8/2024
Posted: 1/22/2022
Updated: 1/23/2022
Page Views: 1109
Topics: #Organica #VisualBasic #VB.NET #ClassLibrary #OrganicaLib
A class for listing all files in the current folder and subfolders.

How many times have you written code to navigate through a series of folders and subfolders in order to list, or process in some way, every file they contain? Well, settle back as we solve that programming problem once and for all with the FileCrawler class!

The reason we keep re-programming this algorithm is that we want to do different things with those files. Perhaps we simply wish to list them, or see how much disk space they take up. We might want to turn some of them into a playlist, or have others copied and reduced in size.

But the answer is actually quite simple. The programmer making use of this library, simply creates an object of this type and has a choice: either let the object popluate a List with one entry per file, or they can provide their own subroutine to perform whatever processing they desire on each file (including ignoring some).

To get started, open the OrganicaLib project and add a class module in the usual way. Name the class (and module) FileCrawler. When Visual Studio has done its thing and opened up the file, add the following statements to the top of the file.

Imports System.IO Public Delegate Sub ProcessCrawledFile(F As FileInfo) Public Class FileCrawler End Class

Next we'll give our class a few properties.

Public Class FileCrawler Public AllFiles As List(Of FileInfo) Private StartingFolder As DirectoryInfo Private MaintainList As Boolean Private Process As ProcessCrawledFile End Class

AllFiles will be our List of files—if the MaintainList property has a value of True. The Process property will hold the address of the user subroutine that is to be called, if supplied.

Setting those properties is, initially, done by the call to create the object.

Public Sub New(StartingFolderMame As String, Optional ShouldDelayCrawl As Boolean = False, Optional Processor As ProcessCrawledFile = Nothing) StartingFolder = New DirectoryInfo(StartingFolderMame) Initialize(ShouldDelayCrawl, Processor) End Sub Public Sub New(aStartingFolder As DirectoryInfo, Optional ShouldDelayCrawl As Boolean = False, Optional Processor As ProcessCrawledFile = Nothing) StartingFolder = aStartingFolder Initialize(ShouldDelayCrawl, Processor) End Sub

As you can see, the New routines allow an object of this class to be created with either the name of the starting directory, or an actual DirectoryInfo object. Because VB.NET doesn't allow one New to call another, I've put the common aspects of initializing into a common, Private function.

Private Sub Initialize(ShouldDelayCrawl As Boolean, Processor As ProcessCrawledFile) MaintainList = IsNothing(Processor) If MaintainList Then AllFiles = New List(Of FileInfo) End If If Not ShouldDelayCrawl Then Crawl(StartingFolder, Processor) End If End Sub

The purpose of the ShouldDelayCrawl parameter, if set to True, is to cause the object to not instantly crawl the folders when it is created. The default value is False, which causes the object to populate the moment it's created, which (if there are a lot of files) could take a few moments.

The Crawl subroutine is where the magic occurs, whether it's called automatically when the object is created, or later when it is explicitly called.

Public Sub Crawl(Folder As DirectoryInfo, YourSubroutine As ProcessCrawledFile) For Each F As FileInfo In Folder.GetFiles If Not IsNothing(YourSubroutine) Then YourSubroutine(F) End If If MaintainList Then AllFiles.Add(F) End If Next For Each Subfolder As DirectoryInfo In Folder.GetDirectories Crawl(Subfolder, YourSubroutine) Next End Sub

This is recursive code, which is why it seems like magic. The subroutine literally calls itself for each subfolder in the current folder.

The task of crawling through a morass of subfolders to list the files isn't horribly difficult, but it's also annoying to have to do over and over. Here's an example of how you might use this class by having it fill a List.

Sub Test1() Dim Files As New FileCrawler("c:\", True) For Each F As FileInfo In Files.AllFiles MsgBox(F.FullName,, F.Name) Next End Sub

And here is how to write a processing subroutine and get the FileCrawler object to invoke it.

Private Sub DisplayFilename(F As FileInfo) MsgBox(F.FullName,, F.Name) End Sub Sub Test2() Dim Files As New FileCrawler("c:\", , False, AddressOf DisplayFilename) End Sub

See? Easy as pie!