Reputation: 93
I'm trying to create an application in C++ that would search all .wav files on the disk (including all subfolders and their subfolders and so on..., whole disk search, like antivirus search on Avast and similar) and store them in a string and save to a text file later on. I'm having troubles figuring out the way on how to actually do this and I could use some help.
This is what I done so far, it's only searching the C drive root folder and I don't know what to do now. I know I should use a loop of some sort but I don't know how to actually do it, there's no logical way that I can think to do it.
void finddata()
{
MessageBox(NULL, "finddata called", "Started", MB_OK | MB_ICONINFORMATION);
WIN32_FIND_DATA FindFileData; // A pointer to the WIN32_FIND_DATA structure that receives information about a found file or directory.
HANDLE hFind; // Used to check the return value
hFind = FindFirstFile("C://*.wav", &FindFileData);
if(hFind == INVALID_HANDLE_VALUE)
{
MessageBox(NULL, "INVALID_HANDLE_VALUE", "Failed", MB_OK | MB_ICONINFORMATION);
}
else
{
string file;
file = FindFileData.cFileName;
file.append("|");
MessageBox(NULL, file.c_str(), "YO", MB_OK | MB_ICONASTERISK); // string.c_str() to conv to LPCSTR
FindClose(hFind);
}
}
The MessageBox at the end is just there as a test, I'll remove it later on. I'm currently learning C++ and this is a sort of a beginner's project so I can get a hang of it.
Also, are there any limitations in size for the string data type? Thanks.
Upvotes: 2
Views: 2269
Reputation: 10242
Recursivity is the way.
Here is a possible implementation (for inspiration, but do it your own way):
// Filtering by the given extension
void AppendFile(list<string>& fileList, const string& directory, const string& fileName, const string& extFilter)
{
string fileExtension = fileName.substr(fileName.find_last_of(".") + 1);
if (!fileExtension.empty())
{
// Extension doesn't match: return
if (extFilter.find(fileExtension) == string::npos)
return;
}
// If we have a match: append file to list
fileList.push_back(directory + fileName);
}
// Getting the files of the given extension recursively (or not)
void GetFiles(list<string>& fileList, string directory, const string& extFilter, bool recursively = true)
{
string filePath;
directory += "\\";
string filter = directory + "*";
WIN32_FIND_DATA FindFileData;
HANDLE hFind = FindFirstFile(filter.c_str(), &FindFileData);
if (hFind == INVALID_HANDLE_VALUE) return;
do
{
// If we find a (sub-)directory
if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
// Here comes the recursive call
if ((recursively) && (lstrcmp(FindFileData.cFileName, TEXT(".")) != 0) && (lstrcmp(FindFileData.cFileName, TEXT("..")) != 0))
// The 'GetFiles()' calls itself on the sub-directory
GetFiles(fileList, directory + FindFileData.cFileName, extFilter);
}
else
// If we find a file: simply append it to the list
AppendFile(fileList, directory, FindFileData.cFileName, extFilter);
}
while (FindNextFile(hFind, &FindFileData) != 0);
FindClose(hFind);
}
Usage :
list<string> fileList;
GetFiles(fileList, "C:\\root_dir", "wav");
for(list<string>::iterator it = fileList.begin(); it != fileList.end(); ++it)
{
cout << (*it) << endl;
}
Upvotes: 1
Reputation: 129314
Obviously, you do indeed need a FindNextFile
call, and repeat that using a loop of some sort, until it returns a "no more files" return code.
To then search the entire disk, you will need to look for directories in the "current directory" (the root directory), and for every directory search into it - you can do that either by calling finddata
recursively (adding the name of the directory as an argument to the function), or implement a stack in the code to track which directory you are in, and which one to "walk back to" for the next level.
I'm intentionally NOT writing the code for you, but describing what you need to do, since you are the one learning programming. I did this sort of thing in 1985 or so.
Upvotes: 2