Click here to Skip to main content
15,860,972 members
Articles / Desktop Programming / MFC
Article

CFileFindEx

Rate me:
Please Sign up or sign in to vote.
4.93/5 (17 votes)
22 Sep 20055 min read 89.7K   1.4K   40   27
A CFileFind with include/exclude filters.

Image 1

Introduction

This article describes how to use CFileFindEx, a class based on the MFC class CFileFind that allows you to specify file filters that control which files are returned. The class plugs in wherever a CFileFind class was used previously and is pretty easy to understand. The programmer can use either DOS wildcard or ATL regular expression based includes or excludes.

Background

My company, Rimage, manufactures high end CD and DVD production equipments. The software I work on specifically is called QuickDisc. It is the interface that helps desktop users collect files using drag and drop and select the options that they want to use when creating discs. Our equipment automatically loads the disc drives and prints on the disc using a printer that we have developed. One of the problems with QuickDisc was that it didn't make a very good back up program because it always selected all the files from folders that were dropped on the UI. The class included in this article was created for an upcoming version to allow us to filter the files based on user input. The class seemed useful and general enough that I thought others may have a use for it.

Using the code

The project download includes the source code for the class and a program that implements its features. The class is simple to use. The programmer can define one or more include or exclude filters in a format similar to the following example:

*.cpp|*.h|*.rc

Note that each filter is separated by a vertical bar '|' character. This character was used because it is not valid for DOS files. If the above is included as an "Include" filter only files with extensions .cpp, .h, or .rc will be returned. Similarly, if the above filter is specified as an "Exclude" filter all files except those of type .cpp, .h, or .rc will be returned.

Note: Folders are always returned regardless of their name or extension.

Alternatively, Include and Exclude filters may be specified using a subset of the typical regular expression syntax as defined in the ATL class CAtlRegExp. The following syntax is allowed:

MetacharacterMeaning
.Matches any single character.
[ ]Indicates a character class. Matches any character inside the brackets (for example, [abc] matches "a", "b", and "c").
^

If this metacharacter occurs at the start of a character class, it negates the character class. A negated character class matches any character except those inside the brackets (for example, [^abc] matches all characters except "a", "b", and "c").

If ^ is at the beginning of the regular expression, it matches the beginning of the input (for example, ^[abc] will only match input that begins with "a", "b", or "c").

-

In a character class, indicates a range of characters (for example, [0-9] matches any of the digits "0" through "9").

?

Indicates that the preceding expression is optional: it matches once or not at all (for example, [0-9][0-9]? matches "2" and "12").

+

Indicates that the preceding expression matches one or more times (for example, [0-9]+ matches "1", "13", "666", and so on).

*

Indicates that the preceding expression matches zero or more times.

??, +?, *?

Non-greedy versions of ?, +, and *. These match as little as possible, unlike the greedy versions which match as much as possible. Example: given the input "<abc><def>", <.*?> matches "<abc>" while <.*> matches "<abc><def>".

\

Escape character: interpret the next character literally (for example, [0-9]+ matches one or more digits, but [0-9]\+ matches a digit followed by a plus character). Also used for abbreviations (such as \a for any alphanumeric character; see table below).

$

At the end of a regular expression, this character matches the end of the input. Example: [0-9]$ matches a digit at the end of the input.

|

Alternation operator: separates two expressions, exactly one of which matches (for example, T|the matches "The" or "the").

!

Negation operator: the expression following ! does not match the input. Example: a!b matches "a" not followed by "b".

AbbreviationMatches
\a

Any alphanumeric character: ([a-zA-Z0-9])

\b

White space (blank): ([ \\t])

\c

Any alphabetic character: ([a-zA-Z])

\d

Any decimal digit: ([0-9])

\h

Any hexadecimal digit: ([0-9a-fA-F])

\n

Newline: (\r|(\r?\n))

\q

A quoted string: (\"[^\"]*\")|(\'[^\']*\')

\w

A simple word: ([a-zA-Z]+)

\z

An integer: ([0-9]+)

For example, the previous filter list could be entered as:

^.*?\.cpp$|^.*?\.h$|^.*?\.rc$

Regular expressions are more trouble to define and only available as an artifact of the way the class does its matching, but some useful expressions could be done:

^[a-d].*?\.cpp$

Would only include (or exclude) files that start with a, b, c, or d and have the extension .cpp. Matches done with this class are always case insensitive.

The class is implemented as in the following example. Don't forget to include filefindex.h.

#include "filefindex.h"

    CString csFilePath = _T("C:\\TestFiles");
    // Include all .doc, .xls, or .ppt files.
    CString csIncludeFilter = _T("*.doc|*.xls|*.ppt"); 
    // Note don't want .doc files that start with Tom
    CString csExcludeFilter = _T("Tom*.doc"); 

    // Check for files based on the critera the user filled out.
    CFileFindEx fileInfo;
    BOOL bWorked = fileInfo.FindFile(csFilePath,csIncludeFilter,
                           csExcludeFilter,bUseRegularExpression);
    if(bWorked) {
        do {
            bWorked = fileInfo.FindNextFile();
            // Do something with the files...
        } while(bWorked);
    }

Points of interest

Anyone who has used CFileFind knows that it is annoying to have to call FindNextFile() before ever even using the file first found in the first call to FindFile(). In trying to make this class work as much like the original as possible, it was tricky to duplicate this illogical logic. However, I think I figured out a way to do it and it seems to work without running any slower than the original in my tests. I've only started using this class so it is pretty new, but I've tested it quite a bit using the included sample program to make sure that my version was just as annoying as the original since we've all gotten kind of used to it.

History

  • September 13th, 2005 - Version 1.0.
  • September 22nd, 2005 - Version 1.1.
  • Fixed problem with calling FindFile() a second (or more) times.
  • Added Unicode support to class and demo.

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


Written By
Software Developer (Senior)
United States United States
I have been using VC++ with MFC since it first came out circa 1993 and I saw it demonstrated at a local Software Development show. I've been working for Rimage Corporation for around 23 years developing software to make our CD and DVD publishing hardware work.

When I'm not working I enjoy hanging out with my family, playing guitar, traveling, and taking my dogs for walks. My family enjoys watching Survivor on Thursday nights and we're not even embarassed by it.

Comments and Discussions

 
Questionfatal error C1189: #error : This file requires _WIN32_WINNT to be #defined at least to 0x0403. Value 0x0501 or higher is recommended. Pin
love071330-Jul-13 16:06
love071330-Jul-13 16:06 
QuestionGetting error: Can not include such file #include "filefindex.h" ? Pin
JyotiranjanR13-Mar-12 18:14
JyotiranjanR13-Mar-12 18:14 
AnswerRe: Getting error: Can not include such file #include "filefindex.h" ? Pin
Thomas Serface13-Mar-12 20:33
Thomas Serface13-Mar-12 20:33 
GeneralProblem building the solution on VS2008 Pin
cohdr0123-Oct-08 3:13
cohdr0123-Oct-08 3:13 
GeneralRe: Problem building the solution on VS2008 Pin
jefflewis12-Jun-09 16:09
jefflewis12-Jun-09 16:09 
GeneralRe: Problem building the solution on VS2008 Pin
jefflewis12-Jun-09 16:18
jefflewis12-Jun-09 16:18 
GeneralBrilliant - thanks for sharing this. Pin
jefflewis18-Feb-08 0:20
jefflewis18-Feb-08 0:20 
GeneralThanks Pin
Mushtaque Nizamani3-Sep-07 23:36
Mushtaque Nizamani3-Sep-07 23:36 
GeneralRe: Thanks Pin
Thomas Serface4-Sep-07 4:08
Thomas Serface4-Sep-07 4:08 
That's great to hear!

Tom
GeneralExcellent job Tom Pin
Ali Rafiee12-Apr-07 14:14
Ali Rafiee12-Apr-07 14:14 
QuestionWhy allow directories to be ok ? Pin
CyberDemonII13-Jan-07 0:32
CyberDemonII13-Jan-07 0:32 
AnswerRe: Why allow directories to be ok ? Pin
Thomas Serface27-Mar-07 11:49
Thomas Serface27-Mar-07 11:49 
GeneralNice job, but got a question Pin
Andromeda Shun13-Oct-05 4:21
Andromeda Shun13-Oct-05 4:21 
GeneralRe: Nice job, but got a question Pin
Thomas Serface13-Oct-05 4:34
Thomas Serface13-Oct-05 4:34 
QuestionHow about a bio, Tom? Pin
Nish Nishant5-Oct-05 10:47
sitebuilderNish Nishant5-Oct-05 10:47 
AnswerRe: How about a bio, Tom? Pin
Tom Serface5-Oct-05 12:24
Tom Serface5-Oct-05 12:24 
GeneralRe: How about a bio, Tom? Pin
Nish Nishant6-Oct-05 7:20
sitebuilderNish Nishant6-Oct-05 7:20 
GeneralRecursive find Pin
nesculcas3-Oct-05 14:28
nesculcas3-Oct-05 14:28 
GeneralRe: Recursive find Pin
Tom Serface4-Oct-05 5:23
Tom Serface4-Oct-05 5:23 
QuestionRegEx Table Pin
Stone Free21-Sep-05 23:10
Stone Free21-Sep-05 23:10 
AnswerRe: RegEx Table Pin
Tom Serface22-Sep-05 4:05
Tom Serface22-Sep-05 4:05 
Questionwork with network folder paths? Pin
Eric Jacobsen20-Sep-05 9:52
Eric Jacobsen20-Sep-05 9:52 
AnswerRe: work with network folder paths? Pin
Thomas Serface21-Sep-05 4:22
Thomas Serface21-Sep-05 4:22 
GeneralRe: work with network folder paths? Pin
Eric Jacobsen21-Sep-05 11:51
Eric Jacobsen21-Sep-05 11:51 
GeneralOK Image Fixed Pin
Tom Serface14-Sep-05 4:22
Tom Serface14-Sep-05 4:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.