Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

File and Directory Enumeration

3 Mar 2003 1  
Template based file and directory enumeration class.

Introduction

Often we need to enumerate files and/or directories and end up writing code like this (pseudocode):

HANDLE hFind = FindFirstFile(...)
while(!lastfile)
{
    // do something if the file is not "." and not ".."

    FindNextFile(...);
}

And since it is so simple we write it again and again. As simple as it seems, it is prone to many errors and we make these errors as often as we write this simple code.

This was the main reason for me to create a template based class to enumerate files and directories. The class does not care about the actual data you need to preserve, or how you represent it. It just cares about correctly recursing a folder and enumerating its content.

The main features of this template class are:

  • thread safety
  • separation of logic from data
  • simple to use

Implementation

The implementation is as follows:

for each folder (which is not '.' or '..')
  if folder should be used
    run the loop again in this folder

for each file 
  if file should be used
    handle the filename
    handle the file

finish processing

The most vital and used functions are the following virtual functions:

virtual bool CheckUseDir(LPCTSTR pstrPath,
WIN32_FIND_DATA* pwfd);

This function is called for every found folder. If the folder should be used, the function has to return true, returning false will skip this folder. The default implementation returns always true.

virtual bool CheckUseFile(LPCTSTR pstrPath,
WIN32_FIND_DATA* pwfd);

This function is called for every found file. It gets passed the full find-file information. If the file should be used, the function has to return true, returning false will skip this file. The default implementation returns always true.

You can implement simple filtering by filename (or extension) like this:

bool CheckUseFile(LPCTSTR, WIN32_FIND_DATA* pwfd)
{
  return ::PathMatchSpec(pwfd->cFileName, _T("*.jpg"));
}
virtual bool HandleRawFile(LPCTSTR pstrFile);

This function is called for every file found after CheckUseFile returned true. If the file should be further used, the function has to return true, returning false will skip this file. The default implementation returns always true.

This function is designed to implement a higher level file processing as it is necessary when you process a archive file. If a archive is considered valid during this function call, one might extract it and then loop again over the extracted files. In this case this function would return false.

virtual void HandleFile(T* pFile); // T being the typename

This function is the last to be called to use the file. Normally one would then store the file information in an array or list.

virtual void FinishedDir(LPCTSTR pstrDir);

After a folder is completely processed this function is called. The folder is not more touched after this function call. You can safely delete the folder for example.

Error handling

If errors occur during any stage of the processing, an error handler (HandleError()) is called. The function is provided with location of the error and the error code. The location is one of the locations defined (RDLOC_xxx)in the class header. The error code is the error code returned by GetLastError().

HandleError() has to return one of the error continuation codes defined (RDEH_xxx) in the class header. You can cause the enumeration to continue with the next folder or file, continue normally, abort or fail by returning the appropriate code.

Starting/Stopping

The file and folder enumeration is started by calling Run(...) with a directory as parameter. You may or may not add a backslash to the directory. The function takes care of proper handling in any case.

To stop the enumeration at any time, call CancelRun(). Stopping is implemented through an event object. If you must attach the class to an existing event you can call SetEvent(...) with your own event handle before starting the enumeration.

Samples

The source code contains also two often used variations: class CDirectoryContent and class CCleanDir.

CDirectoryContent delivers an array (std::vector or CArray) of files contained in the directory provided and CCleanDir recursively erases all files in the directory.

The demo project includes a CDirectoryContent derived class which implements a simple wildcard filter.

Compatibility

Written, compiled and tested with VC6 SP5. Unicode safe. Requires Version 4.71 or later of Shlwapi.dll (uses Path...() functions). If used with in a MFC project it will use CString and CArray classes, otherwise it uses std::string and std::vector.

References

Have a look also at some of the other implementations here at CodeProject:

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here