XTab's Blog

Ged Mead's Blog at vbCity

vbCity Blogs moved to:
http://cs.vbcity.com/blogs
  Home :: Syndication  :: Login

MayJune 2008Jul
SMTWTFS
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

Archives

Topics

Ramblings

VB.NET

Wednesday, June 04, 2008 #

   I was looking for a task to use as the background task of my recent article on the BackgroundWorker component and decided that I'd use a recursive search through folders.   Ironically, I ended up spending about twice as much time on getting the recursive search procedures running correctly than I spent on the main BackgroundWorker code.

   As I ended up with three varieties of recursive searches - and found  some things that should have worked, but didn't seem to - I thought I'd blog it.

  To find a particular file type in folders and sub-folders I used this code:

Code Copy
Sub FileFinder(ByVal dir As String)

        Try

            ' Display all files in a directory that match file type
            For Each fname As String In IO.Directory.GetFiles(dir)
                If fname.EndsWith("txt") Then
                    '  pass back progress message
                    Console.WriteLine(fname)
                End If
            Next

            ' A recursive call for all the subdirectories in this directory.
            For Each subdir As String In IO.Directory.GetDirectories(dir)
                FileFinder(subdir)
            Next
        
        Catch ex As Exception
            MessageBox.Show(ex.Message.ToString)

        End Try
    End Sub
 

   You'll probably have spotted that I used the "EndsWith" function there to test for the tile type I'm interested in.   Originally I tried using the SearchPattern parameter of the GetFiles method, but for whatever reason it didn't identify the files for me.

  Another little glitch to keep in mind is that there may be some files to which users don't have authorised access.  If for example you call the above code and pass in "C:\" as the argument you will probably get one or more "Access Denied" messages via the Exception Handler.  Of course, because the exception is being handled, the user can click on the messagebox's OK button and the procedure will continue to run.

  Obviously, to avoid the message appearing at all you can just comment out the MessageBox.

  If you want to home in on that particular issue and allow access but still want to know if other kinds of problems occur then you can fine tune your structured exception handlers (as of course you should) and include a handler specifically aimed at the access exception:

Code Copy
Catch ioex As System.UnauthorizedAccessException

   ' Access Denied Problem will be handled here

Catch ex As Exception

    ' Other Exceptions will be flagged up to users


    MessageBox.Show(ex.Message.ToString)

  Hard coding the file type limits reusability, so a better version would be:

Code Copy
  Sub FileTypeFinder(ByVal dir As String, ByVal FileExt As String)

        Try
            ' Display all files in a directory that match file type
            For Each fname As String In IO.Directory.GetFiles(dir)
                If fname.EndsWith(FileExt) Then
                    '  pass back progress message
                    Console.WriteLine(fname)
                End If
            Next

            ' A recursive call for all the subdirectories in this directory.
            For Each subdir As String In IO.Directory.GetDirectories(dir)
                FileTypeFinder(subdir, FileExt)
            Next

        Catch ioex As System.UnauthorizedAccessException

        Catch ex As Exception
            MessageBox.Show(ex.Message.ToString)

        End Try

    End Sub

 

  The client now passes in the file type as well as the parent folder.

 

   The final version I used was one which recursively searched through folders and subfolder, found files that matched a particular file extension and then searched inside matching files for a particular string.  This of course could be a particularly long task in some cases and so a good candidate for the BackgroundWorker. 

Code Copy
    Private Sub FileContentFinder(ByVal dir As String, ByVal FileExt As String, _
                                 ByVal TargetText As String)
        Dim rdr As IO.StreamReader

        Try

            ' Display all files in a directory that match file type
            For Each fname As String In IO.Directory.GetFiles(dir)
                If fname.EndsWith(FileExt) Then
                    rdr = New IO.StreamReader(fname)
                    Dim strFileContents As String = rdr.ReadToEnd
                    rdr.Close()
                    rdr = Nothing

                    ' If this file contains the target string, pass back progress message
                    If strFileContents.Contains(TargetText) Then
                        Console.WriteLine(fname)
                    End If
                End If
            Next

            ' A recursive call for all the subdirectories in this directory.
            For Each subdir As String In IO.Directory.GetDirectories(dir)
                FileContentFinder(subdir, FileExt, TargetText)
            Next

        Catch ex As Exception
            MsgBox(ex.Message.ToString)

        End Try

    End Sub

 

   There are many other twists you could use on the above approaches, such as testing against file attributes for dates, for example, or copying files that meet certain criteria.  

posted @ 4:10 PM | Feedback (0)