Click here to Skip to main content
13,197,767 members (42,802 online)
Click here to Skip to main content
Add your own
alternative version

Stats

217.2K views
5.7K downloads
100 bookmarked
Posted 5 Aug 2002

CFileFinder - Extend the functionality of CFileFind MFC class

, 15 Aug 2002
Rate this:
Please Sign up or sign in to vote.
Search for files by name, size, date, text contents. The search can be performed in a single folder or including it's subfolders.

Sample Image - image.gif

Introduction

CFileFinder uses CFileFind to perform a file search starting from a directory and including optionally it's subdirectories in the search.

  • A list of file paths is mantained internally.
  • If we make use of the callback mechanism, new found file paths can be obtained immediatly.
  • The class allows not only searches based on a file mask but also on the file size, file dates, text contents and file attributes.

Class methods

FindFiles

int FindFiles(LPCTSTR szBaseFolder, LPCTSTR szFileMask, BOOL bSubFolders = FALSE)

Search for files which match the mask szFileMask. This file mask can include one or more wildcard characters (* and ?)

Find

int Find(CFileFinder::CFindOpts &opts)

Find files matching the conditions established in the CFindOpts class parameter (See explanation of CFindOpts below)

FindTextInFile

BOOL FindTextInFile(LPCTSTR szFile, LPCTSTR szText)

Return TRUE if the text szText was found in the file szFile. It's internally used by the Find method. It's declared public to allow applications make use of this functionality.

GetFileCount

int GetFileCount()

Return the count of items found up to the moment the call is performed or the total of files found in the last Find or FindFiles operation.

GetFilePath

CPath GetFilePath(int nIndex)

Return a CPath object with the required file index path. In the CPath class there are two useful operators defined: operator LPCTSTR () and operator = (LPCTSTR szPath) which allows, for instance, direct assign from and to a CString object.

// ...

CString str1("c:\\temp\\list.txt"), str2;
CPath path;

path = str1;
str2 = path;

// at this point, str2 contains the 
// string "c:\temp\list.txt"

For more information about the CPath class see the related article.

FindPathItem

int FindPathItem(LPCTSTR szPath)

Return the index of the file whose path matches szPath or -1 if the file is not in the list.

RemoveAt

void RemoveAt(int nIndex)

Remove item at nIndex position.

RemoveAll

void RemoveAll()

Remove all items from the list.

SetCallback

void SetCallback(FILEFINDERPROC pFileFinderProc, void *pCustomParam)

Set the callback function pointer used by the search process from the Find method. The callback function is defined in the following way:

void FileFinderProc(CFileFinder *pFinder, 
        DWORD   dwCode, void    *pCustomParam);
  • pFinder .- The calling CFileFinder object
  • dwCode .- The calling reason:
    • FF_FOUND - A new file was found
    • FF_DISCARDED - A file matched the file mask but not all the conditions
    • FF_FOLDER - The search in a new folder started
    • FF_FINDTEXT - Searching for text in a file. This gives our applications the chance to process messages while searching text on big files.
  • pCustomParam .- The same pointer passed to the function SetCallback.

The name of the new found file, when the dwCode parameter is FF_FOUND, can be obtained with a call like this:

pFinder->GetFilePath(pFinder->GetFileCount() - 1);

StopSearch

void StopSearch()

If this method is called from within the FileFinderProc callback function, the find process is stopped but the list of files is not deleted.

GetSearchingFolder

LPCTSTR GetSearchingFolder()

Calling this method from FileFinderProc when the dwCode parameter is FF_FOLDER, the name of the folder being searched is retrieved.

The CFindOpts class

This class help us configuring the search to be carried out. Its methods are simple helpers to set the class members easily for the most common searches.

Class members explained

  • dwOptionsFlags - This flags indicate the constrains to be taken into account apart from the file mask
    • FIND_SIZE - If the size of a file that matches the file mask is not in the range [nMinSize, nMaxSize], the file is discarded.
    • FIND_DATEMODIFIED - The last modified file date must be in the range [tMinModified, tMaxModified]
    • FIND_DATECREATED - The creation file date must be in the range [tMinCreated, tMaxCreated]
    • FIND_DATEACCESSED - The last accessed file date must be in the range [tMinAccessed, tMaxAccessed]
    • FIND_ATTRIBUTES - The attributes of the file found must match the dwFileAttributes member (this member can take the same values as the one with the same name in WIN32_FIND_DATA struct)
    • FIND_TEXT - The file has to contain the text specified in sFindText
  • sBaseFolder - The search root folder
  • sFileMask - The file mask (e.g.: "*.txt", "fi?e.*")
  • sFindText - Text that must be found in a file to consider it a match. Note that the flag FIND_TEXT must be added to dwOptionsFlags. If sFindText is empty the text search is not performed even if the FIND_TEXT is set
  • bSubfolders - A boolean indicating whether the search must include subdirectories or not
  • nMinSize / nMinSize - The file size range when the FIND_SIZE flag is set
  • tMinCreated / tMaxCreated - The file creation date range when the FIND_DATECREATED flag is set
  • tMinModified / tMaxModified - The file last modified range when the FIND_DATEMODIFIED flag is set
  • tMinAccessed / tMaxAccessed - The file last accessed range when the FIND_DATEACCESSED flag is set
  • dwFileAttributes - The file attributes when the FIND_ATTRIBUTES is set

Class methods

void Reset()

  • empty sBaseFolder
  • set sFileMask to "*.*"
  • set bSubFolders to FALSE
  • set nMinSize, nMaxSize to 0
  • reset dwFileAttributes and dwOptionsFlags flags
  • set all date members to the current date and time

void FindNormalFiles()

  • add normal files (FILE_ATTRIBUTE_ARCHIVE) to the search
  • add FIND_ATTRIBUTES to dwOptionsFlags

void FindAllFiles()

  • add all files attributes to the search, even hidden files, system files.
  • add FIND_ATTRIBUTES to dwOptionsFlags

void FindDirectories()

  • add directories to the search (directories have an own attribute: FILE_ATTRIBUTE_DIRECTORY)
  • add FIND_ATTRIBUTES to dwOptionsFlags

void FindText(LPCTSTR szText)

  • set sFindText to szText
  • add FIND_TEXT to dwOptionsFlags

Notes

The CPath class requires linking with the library shlwapi.lib

Sample code can be found in the source of the sample application provided with this article

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

Samuel Gonzalo
Software Developer (Senior)
Spain Spain
I studied Telecommunication with spezialization in Sound & Image. I was always very interested in programming at university as well and that is how I earn a living.

Since some years ago, I am also succesfully involved in software architecture and design.

You may also be interested in...

Comments and Discussions

 
QuestionDoesn't compile against VS2015 or VS2017? Pin
Member 50428-Sep-17 3:25
memberMember 50428-Sep-17 3:25 
QuestionGot CInvalidArgException error while finding text. Pin
Member 1075462516-May-14 23:15
memberMember 1075462516-May-14 23:15 
QuestionHere is a BUG with compiling... Pin
cyfage12-Aug-12 14:15
membercyfage12-Aug-12 14:15 
AnswerRe: Here is a BUG with compiling... Pin
Samuel Gonzalo25-Aug-12 23:35
memberSamuel Gonzalo25-Aug-12 23:35 
AnswerRe: Here is a BUG with compiling... Pin
Samuel Gonzalo25-Aug-12 23:42
memberSamuel Gonzalo25-Aug-12 23:42 
GeneralUnicode support Pin
malfaro23-Aug-10 10:38
membermalfaro23-Aug-10 10:38 
GeneralFileFinder and Path code for VS2008 Pin
AntoineBab2-Jan-10 22:34
memberAntoineBab2-Jan-10 22:34 
GeneralRe: FileFinder and Path code for VS2008 Pin
lows22-Jan-10 2:47
memberlows22-Jan-10 2:47 
Questionhow to search office word 2003 Pin
JackJianShen2-Sep-09 22:09
memberJackJianShen2-Sep-09 22:09 
GeneralQuestion to the function "CPath CFileFinder::GetFilePath(int nIndex)" Pin
Golden Lee2-Apr-09 16:28
memberGolden Lee2-Apr-09 16:28 
GeneralRe: Question to the function "CPath CFileFinder::GetFilePath(int nIndex)" Pin
Samuel Gonzalo15-Jul-09 20:27
memberSamuel Gonzalo15-Jul-09 20:27 
GeneralCompiling with VS2008 Pin
RedFraggle25-Feb-09 12:32
memberRedFraggle25-Feb-09 12:32 
GeneralChanging the access date Pin
anitaj7-Jul-08 20:24
memberanitaj7-Jul-08 20:24 
GeneralTHNX Pin
CTAPYLLIKA20-Mar-08 20:55
memberCTAPYLLIKA20-Mar-08 20:55 
QuestionInheritance ? Pin
./w10-Oct-07 13:21
member./w10-Oct-07 13:21 
AnswerRe: Inheritance ? Pin
Samuel Gonzalo19-Nov-07 11:04
memberSamuel Gonzalo19-Nov-07 11:04 
GeneralMAX_PATH Pin
superagenteg3-Oct-07 0:57
membersuperagenteg3-Oct-07 0:57 
GeneralRe: MAX_PATH Pin
Samuel Gonzalo19-Nov-07 11:28
memberSamuel Gonzalo19-Nov-07 11:28 
GeneralWarnings are appeared when I try to Rebuild the solution [modified] Pin
Nenad B23-Mar-07 4:18
memberNenad B23-Mar-07 4:18 
Questionhow to search through Zip folders Pin
maddy_sv30-Nov-06 3:48
membermaddy_sv30-Nov-06 3:48 
Generalsome extensions Pin
aldo hexosa5-Nov-06 15:31
memberaldo hexosa5-Nov-06 15:31 
GeneralCorrection for file matching logic Pin
Steve Mayfield11-Sep-06 12:41
memberSteve Mayfield11-Sep-06 12:41 
GeneralVC 7.1 compilation problems [modified] Pin
Yenidai_23-Jun-06 0:18
memberYenidai_23-Jun-06 0:18 
General_finder.SetCallback(FileFinderProc, this); ERROR [modified] Pin
locoone11-Jun-06 12:28
memberlocoone11-Jun-06 12:28 
Generalplease use static Callback Function! Pin
swqswqswqswq17-Jun-06 20:42
memberswqswqswqswq17-Jun-06 20:42 
QuestionDoes not work over the network? Pin
Kyp8311-Jul-05 7:23
memberKyp8311-Jul-05 7:23 
AnswerRe: Does not work over the network? Pin
The incredible machine21-Jun-07 22:25
memberThe incredible machine21-Jun-07 22:25 
GeneralAdding wildcard directory matching Pin
Steve Mayfield4-Feb-05 21:13
memberSteve Mayfield4-Feb-05 21:13 
QuestionRe: Adding wildcard directory matching Pin
dipali_be200325-Aug-06 20:53
memberdipali_be200325-Aug-06 20:53 
GeneralLogic Error found Pin
Thomas de Rossi5-Nov-04 8:22
memberThomas de Rossi5-Nov-04 8:22 
GeneralNice Article Pin
VivekAnna29-Jun-04 20:44
memberVivekAnna29-Jun-04 20:44 
GeneralDiscrepancy found Pin
oksale14-Apr-04 21:56
memberoksale14-Apr-04 21:56 
GeneralRe: Discrepancy found Pin
oksale15-Apr-04 22:04
memberoksale15-Apr-04 22:04 
I have found the decision of a problem.
First I shall result a fragment from article:

It was a big surprise to me when I found that the FindFileFirst Win32 API function finds a match to wildcard by using deprecated DOS rules.
In Windows 95, the situation got better ... or maybe, it was worse... Long filenames were added, but "short" filenames were saved for "compatability" with old programs. For each program with a "long" filename, Windows had auto-generated a "short" filename. When a program searches the file by wildcard, Windows decides that a match happens if it matches a long OR short name. For example, if you search "*.aaa" you will find "a.aaa" but also "verylongname.aaaa" because its short name is "verylo~1.aaa" and it matches "*.aaa".

Why am I telling that touching story? Because I've used Windows 2000 for a very long time, I've used Explorer's Find Files dialog, or FAR's manager Find File plugin, and never issued the behavior described above. But recently I had found an excellent utility dirclean by Michael Dunn, which led me to a surprise: that deprecated wildcard matches are built into Windows 2000 (or XP) also! I found this by accident: This useful utility integrates into the shell and deletes intermediate files of Visual C++ builds, by searching with a wildcard. And while deleting, among all others, all "*.res" files which are scratch and rebuildable, it also deletes "*.resx" files, which are NOT!!!

The problem is in the FindFirstFile/FindNextFile API and it touches all Windows versions currently existing (till XP, included).


That it is necessary to change code from
<br />
int CFileFinder::Find(CFileFinder::CFindOpts &opts)<br />
{<br />
......<br />
if (bValidFile)<br />
{<br />
  CString sName = finder.GetFilePath();<br />
  if (finder.IsDirectory()) sName += "\\";<br />
  _aFilesFound.Add(sName);<br />
  bValidFile = TRUE;<br />
}<br />
 // Call callback procedure<br />
 if (_pFileFinderProc != NULL)<br />
  _pFileFinderProc(this, bValidFile ? FF_FOUND : FF_DISCARDED, _pCustomParam);<br />
.....<br />
return GetFileCount();<br />
}<br />


to
<br />
int CFileFinder::Find(CFileFinder::CFindOpts &opts)<br />
{<br />
......<br />
if (bValidFile)<br />
{<br />
	CString sName = finder.GetFilePath();<br />
	if (finder.IsDirectory()) sName += "\\";<br />
<br />
	// file name<br />
	CString sN = finder.GetFileName();<br />
	// position of dot in founded file<br />
	int dot = sN.ReverseFind('.');<br />
	// position of dot in mask<br />
	int dotM = opts.sFileMask.ReverseFind('.');<br />
	// get extension of founded file<br />
	CString sFound = sN.Right(sN.GetLength() - dot - 1);<br />
	// get extension of mask<br />
	CString sMask = opts.sFileMask.Right(opts.sFileMask.GetLength() - dotM - 1);<br />
	// position of * in mask<br />
	int iPos = sMask.Find('*');<br />
<br />
	// if "." exists in extension of mask<br />
	if(dotM != -1)<br />
	{<br />
		// if length of extensions of mask and founded file are equal<br />
		// for ex. mask: *.res, *.re?, founded file: answer.res<br />
		if(sFound.GetLength() == sMask.GetLength())<br />
		{<br />
			_aFilesFound.Add(sName);<br />
			bValidFile = TRUE;<br />
		}<br />
		// if length of extensions of mask and founded file are not equal<br />
		if(sFound.GetLength() != sMask.GetLength())<br />
		{<br />
			// * exists in mask<br />
			// for ex. mask: *.res*, founded file: answer.resa<br />
			if(iPos != -1)<br />
			{<br />
				_aFilesFound.Add(sName);<br />
				bValidFile = TRUE;<br />
			}<br />
			// * don't exists in mask<br />
			else<br />
				bValidFile = FALSE;<br />
		}<br />
						<br />
	}<br />
	else<br />
	{<br />
		_aFilesFound.Add(sName);<br />
		bValidFile = TRUE;<br />
	}<br />
<br />
 } // Call callback procedure<br />
 if (_pFileFinderProc != NULL)<br />
  _pFileFinderProc(this, bValidFile ? FF_FOUND : FF_DISCARDED, _pCustomParam);<br />
.....<br />
return GetFileCount();<br />
<br />

Generala little problem Pin
Foerst30-Mar-04 9:25
memberFoerst30-Mar-04 9:25 
GeneralRe: a little problem Pin
Samuel Gonzalo30-Mar-04 19:32
memberSamuel Gonzalo30-Mar-04 19:32 
GeneralCORRECTION FOR SEARCH FILES IN CDROM Pin
ikwi19-Aug-03 11:22
memberikwi19-Aug-03 11:22 
GeneralSupport on the NT 4 SP6A Pin
Anonymous12-Aug-03 22:25
sussAnonymous12-Aug-03 22:25 
GeneralRe: Support on the NT 4 SP6A Pin
Anthony_Yio12-Aug-03 23:08
memberAnthony_Yio12-Aug-03 23:08 
GeneralRe: Support on the NT 4 SP6A Pin
avistav24-Sep-03 2:22
memberavistav24-Sep-03 2:22 
GeneralRe: Support on the NT 4 SP6A Pin
Anthony_Yio24-Sep-03 16:30
memberAnthony_Yio24-Sep-03 16:30 
GeneralRe: Support on the NT 4 SP6A Pin
avistav24-Sep-03 19:52
memberavistav24-Sep-03 19:52 
GeneralRe: Support on the NT 4 SP6A Pin
Nicholas Wourms25-Jul-05 17:46
memberNicholas Wourms25-Jul-05 17:46 
GeneralVery usefull but I changed this.. Pin
jhaga7-Apr-03 9:39
memberjhaga7-Apr-03 9:39 
QuestionWay to take advantage of Microsoft's low-level search functionality? Pin
ame1219-Jan-03 7:38
memberame1219-Jan-03 7:38 
AnswerRe: Way to take advantage of Microsoft's low-level search functionality? Pin
peterchen19-May-05 10:10
memberpeterchen19-May-05 10:10 
GeneralVery nice but a small problem Pin
Nyrup19-Dec-02 19:45
memberNyrup19-Dec-02 19:45 
Generalhelp with supporting image thumbnails Pin
Otyug31-Oct-02 18:28
memberOtyug31-Oct-02 18:28 
GeneralNice tool Pin
DerMeister16-Aug-02 3:21
memberDerMeister16-Aug-02 3:21 
GeneralUpdate 16th August Pin
Samuel Gonzalo15-Aug-02 23:14
sussSamuel Gonzalo15-Aug-02 23:14 
GeneralLittle bug in Path.cpp Pin
Anonymous7-Aug-02 21:24
sussAnonymous7-Aug-02 21:24 

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.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.171020.1 | Last Updated 16 Aug 2002
Article Copyright 2002 by Samuel Gonzalo
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid