![]() |
Searching for files seems to be a common theme in most of my programs - Webifier actually searches multiple times, one time for pictures, and another time for folders, and yet another time for all the files associated with a style. Each search has slightly different criteria, and performs a slightly different function with the found files, but in all cases the pattern is the same:
WIN32_FIND_DATA filedata;
HANDLE handle = ::FindFirstFile(path, &filedata)
if ( INVALID_HANDLE_VALUE != handle ) do
{
if ( criteria are met )
do something with file
} while ( ::FindNext(handle, &filedata) )
::FindClose(handle)
Well, I hate writing the same code more than once, so I looked for a way to consolidate the code for all my file-finding. The notable thing about this code is that only the contents of the do loop change, an ideal case for a sort of policy-based template. So I wrote a template function to implement the basic pattern, and a few functors to implement the specific "policies":
template <class FileAcceptor>
void find_files(string folder, FileAcceptor fa)
{
WIN32_FIND_DATA found_file;
string delim = ((folder.find_last_of("\\") == folder.npos) ? "" : "\\");
HANDLE h_find = ::FindFirstFile( (folder + delim + "*.*").c_str(), &found_file );
if ( INVALID_HANDLE_VALUE != h_find ) {
do {
fa(folder + delim, found_file);
} while ( ::FindNextFile(h_find, &found_file) );
::FindClose(h_find);
}
}
With this bit of code, all I need to do is write some policies to filter and process individual files, and I don't have to worry about the messy details every again. So for example, you could fill a drop down box with a list of folder names like this:
box is a VCL TComboBox string path = ...; // starting path to search find_files(path, LoadStyleNames(box->Items));
where the LoadStyleNames functor looks like this:
class LoadStyleNames
{
public:
LoadStyleNames(TStrings *s):m_s(s) {}
void operator()(const string &src_folder, const WIN32_FIND_DATA &file) {
static string dotdot(".."), dot(".");
if ( ( file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
&& dotdot != file.cFileName && dot != file.cFileName ) {
m_s->Add(file.cFileName);
}
}
private:
TStrings *m_s;
};
And that's it! The functor is called once for each found file, so all it has to do is see if that file meets your criteria, and if so, decide what to do with it. WIN32_FIND_DATA doesn't provide the whole pathname, so it's provided as a parameter with each call. As written, sub-folders aren't searched, but this can be easily added as a recursive call within the functor:
class SearchSubFolders
{
public:
...
void operator()(const string &src_folder, const WIN32_FIND_DATA &file) {
static string dotdot(".."), dot(".");
if ( ( file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
&& dotdot != file.cFileName && dot != file.cFileName ) {
find_files(src_folder + file.cFileName + "\\", SearchSubFolders());
}
else
{
...
}
}
...
};
So, there's one handy-dandy template function to handle all your file-searching needs. Enjoy!
| Latest Releases |
| Webifier 1.1.0 - 11/14/2007 - Show your pictures to the world with this web photo gallery creator. |
| PictureSaver 4.2.5 - 03/10/2006 - Turn your pictures into a slideshow screensaver; great with digital cameras! |
| RandomSaver 2.0.3 - 06/14/2002 - Got a lot of screen savers? Why watch just one? RandomSaver lets you watch 'em all! |
| GullBlaster 1.1 - 05/12/2002 - Tired of them seagulls? Now you can get even! Blast them before they blast you! |
| FontViewer 1.1.1 - 06/13/2002 - Preview all the installed fonts on your system. |
| Monitor page for changes |
|
powered by ChangeDetection |