Click here to Skip to main content
Click here to Skip to main content

CFileFindEx

, 22 Sep 2005
Rate this:
Please Sign up or sign in to vote.
A CFileFind with include/exclude filters.

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:

Metacharacter Meaning
. 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".

Abbreviation Matches
\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

Share

About the Author

Thomas Serface
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. Pinmemberlove071330-Jul-13 16:06 
QuestionGetting error: Can not include such file #include "filefindex.h" ? PinmemberJyotiranjanR13-Mar-12 18:14 
AnswerRe: Getting error: Can not include such file #include "filefindex.h" ? PinmemberThomas Serface13-Mar-12 20:33 
GeneralProblem building the solution on VS2008 Pinmembercohdr0123-Oct-08 3:13 
GeneralRe: Problem building the solution on VS2008 Pinmemberjefflewis12-Jun-09 16:09 
GeneralRe: Problem building the solution on VS2008 Pinmemberjefflewis12-Jun-09 16:18 
GeneralBrilliant - thanks for sharing this. Pinmemberjefflewis18-Feb-08 0:20 
GeneralThanks PinmemberMushq3-Sep-07 23:36 
GeneralRe: Thanks Pinmembertserface4-Sep-07 4:08 
That's great to hear!
 
Tom
GeneralExcellent job Tom PinmemberAli Rafiee12-Apr-07 14:14 
QuestionWhy allow directories to be ok ? PinmemberCyberDemonII13-Jan-07 0:32 
AnswerRe: Why allow directories to be ok ? Pinmembertserface27-Mar-07 11:49 
GeneralNice job, but got a question PinmemberAndromeda Shun13-Oct-05 4:21 
GeneralRe: Nice job, but got a question Pinmembertserface13-Oct-05 4:34 
QuestionHow about a bio, Tom? PinstaffNishant Sivakumar5-Oct-05 10:47 
AnswerRe: How about a bio, Tom? PinmemberTom Serface5-Oct-05 12:24 
GeneralRe: How about a bio, Tom? PinstaffNishant Sivakumar6-Oct-05 7:20 
GeneralRecursive find Pinmembernesculcas3-Oct-05 14:28 
GeneralRe: Recursive find PinmemberTom Serface4-Oct-05 5:23 
QuestionRegEx Table PinmemberStone Free21-Sep-05 23:10 
AnswerRe: RegEx Table PinmemberTom Serface22-Sep-05 4:05 
Questionwork with network folder paths? PinmemberEric Jacobsen20-Sep-05 9:52 
AnswerRe: work with network folder paths? Pinmembertserface21-Sep-05 4:22 
GeneralRe: work with network folder paths? PinmemberEric Jacobsen21-Sep-05 11:51 
GeneralOK Image Fixed PinmemberTom Serface14-Sep-05 4:22 
Generalscreenshot missing Pinmemberbruno leclerc13-Sep-05 21:37 
NewsRe: screenshot missing PinmemberRavi Bhavnani14-Sep-05 2:15 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140827.1 | Last Updated 22 Sep 2005
Article Copyright 2005 by Thomas Serface
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid