Results 1 to 7 of 7

Thread: VB6 - DirLister lightweight Dir() wrapper

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Lightbulb VB6 - DirLister lightweight Dir() wrapper

    People seem to get befuddled about the proper use of VB's Dir() function. A big part of the reason is that it is actually a stateful object that performs two different operations. Another is probably because it does not descend into subdirectories.

    The usual approach to handling recursive descent into subdirectories with Dir() is to write a recursive function. Often this means buffering results and returning them as an array, collection, or other data structure full of the file and subfolder names. This can be fairly heavy when you need to traverse a large and deep folder structure.

    Here I have taken another approach, and one you can easily drop into your own Projects. It takes advantage of the fact that Dir() is a lightweight wrapper on FindFirstFile(), etc. API calls. Its performance should be such that you will never need to resort to cumbersome API calling code unless you require proper handling of Unicode file names - which most of the rest of VB's native I/O statements don't handle either.


    DirLister

    A wrapper Class providing a global predeclared object for using VB 's Dir() intrinsic function more easily.

    DirLister handles subdirectory descent without using recursion and provides a mechanism to retrieve files or files and folders with a one by one call.

    It can be easier to use than recursive methods and should be much lighter in terms of resources used. While it uses a tree of Collection objects these are populated gently and trimmed back aggressively.


    Properties

    Busy
    Code:
    Busy As Boolean (read only)
    Seldom used, but returns True when a search has been started and not yet finished. While True you cannot start another search because it will interrupt the internal state of VBA.Dir().


    Methods

    Start
    Code:
    Start(ByVal SearchPath As String, _
          Optional ByVal Attributes As VbFileAttribute = vbNormal,
          Optional ByVal FilePattern As String = "*.*")
    First call Start() passing the SearchPath, FilePattern, and Attributes desired.

    The pattern is applied only to file names and not subdirectory names. If Attributes has the vbDirectory bit set then directory names are returned as well as file names.

    Dir
    Code:
    Dir(ByRef Path As String) As Boolean
    After Start() you can call Dir() passing a String variable to receive the file or directory name. Dir() returns True until there are no more names to be returned.

    Finish
    Code:
    Finish()
    When Dir() returns False (or whenever you abandon a search) you must call Finish() to release the underlying handles and reset for the next new Start() call.


    Notes
    • The Class provides a GLOBAL PREDECLARED INSTANCE and you do not need (or really want) to create additional instances of it. Since VBA.Dir() is stateful only one could be actively in use at a time anyway.
    • This Class is dependent upon the Class DirLNode which it uses internally.
    • The FilePattern pattern is much richer than using patterns with Dir() calls. You have the full range of VB6 "Like" operator patterns. The pattern operates on the simple name part of retrieved file names and not the entire full path.
    • Files and paths with Unicode symbols or blocked by security will be silently skipped.
    • Calling Dir() in your own code while a search has been started will destroy the process because it changes the internal state of Dir(). This is true for any use of Dir() and not specific to this Class.


    Using DirLister

    Just add DirLister.cls and the helper Class DirLNode.cls to your Project.

    DirLister is provided here as a demo project showing how to use it.
    Attached Files Attached Files

  2. #2

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: VB6 - DirLister lightweight Dir() wrapper

    Please report any bugs found in this code. It is easy to get wrapped around the axle writing this sort of thing, as you can see by reading through the logic there. I might never write another blob of Dir() code myself.

  3. #3
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    Re: VB6 - DirLister lightweight Dir() wrapper

    Thanks, nice code.

    Not a bug, but one minor change I made is to put the Dir = mAttributes And vbDirectory code after the If DirReturn <> "." And DirReturn <> ".." Then test, because I have a bunch of code littered with tests to fillter out the "." and ".." folders, so it would be nice to just omit those tests entirely.

    Maybe an boolean property would be more appropriate (to mimic the VBA.Dir$() exactly, or prevent "." and ".." from being matched), but just a thought.

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: VB6 - DirLister lightweight Dir() wrapper

    I understand your point and considered this when I wrote the code.

    You can make a change such as hardcoding it to never return "." or ".." relative links. You could add another property or Start() parameter or something to let the caller choose. You might even make your own special Enum to replace VbFileAttribute on DirLister.Start() calls, the same as VbFileAttribute with an additional unique value to mean "I want the relative directory links back."

    I think you're right that you seldom want them back though.

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: VB6 - DirLister lightweight Dir() wrapper

    DirLister 2 addresses the issue discussed above, and also adds a Depth argument to Start(). See the comments at the head of the DirLister.cls source code.
    Attached Files Attached Files

  6. #6

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: VB6 - DirLister lightweight Dir() wrapper

    DirLister 3 handles inaccessible filesystem objects (by skipping them rather than throwing an exception).

    It is still entirely non-recursive, provides a call-per-item interface making it easy to use in your loops, and now doesn't use any Collection objects for caching directory levels.

    Performance should be close enough to API level perfomance for almost any practical purpose and might even exceed it due to the overhead involved in every call to a Declared entrypoint.

    No Unicode support of course. Dir$() was never built for that.

    There are two constants that can be tweaked within the DirlNode Class to tune array resizing if desired. If you expect to be working with large numbers of subdirectories raising these values might improve performance.
    Attached Files Attached Files
    Last edited by dilettante; Jan 12th, 2012 at 02:58 PM.

  7. #7

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: VB6 - DirLister lightweight Dir() wrapper

    Minor update to optimize cases where the FilePattern is "*" (default) or "*.*" (same result really) which should increase the speed slightly for those cases.
    Attached Files Attached Files

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width