Reputation: 625
I am failing to see where i am going wrong. This current code skips straight to closefile. NOt processing any files, i may just be missing something obvious and it has been a long day.
My function is meant to search the hard disk (c:) for a given file. EG example.txt. &strFilePath here would be used in the FindFirstFile declaration.
Any help would be appeciated.
Thanks.
String Copy::SearchDrive( const String& strFile, const String& strFilePath, const bool& bRecursive, const bool& bStopWhenFound ) const
{
HANDLE hFile;
WIN32_FIND_DATA file;
hFile = FindFirstFile("C:\\", &file);
String strFoundFilePath = "";
if ( hFile )
{
while ( FindNextFile( hFile, &file))
{
String strTheNameOfTheFile = file.cFileName;
// It could be a directory we are looking at
// if so look into that dir
if ( file.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY
&& bRecursive )
{
String strNewFilePath = strFilePath + "\\";
strNewFilePath += strTheNameOfTheFile;
SearchDrive( strFile, strNewFilePath, bRecursive, bStopWhenFound );
}
else
{
if ( strTheNameOfTheFile == strFile )
{
strFoundFilePath = strFilePath;
strFoundFilePath += "\\";
strFoundFilePath += strFile;
/// TODO
// ADD TO COLLECTION TYPE
if ( bStopWhenFound )
{
break;
}
}
}
}
CloseHandle( hFile );
}
return strFoundFilePath;
}
Upvotes: 8
Views: 24644
Reputation: 598448
You have quite a few logic bugs in your code. Try this instead (you did not indicate which compiler you are using, so I am assuming C++Builder, which has an uppercase-S String
class. Adjust the code as needed if you are using a different compiler):
String Copy::SearchDrive(const String& strFile, const String& strFilePath, const bool& bRecursive, const bool& bStopWhenFound) const
{
String strFoundFilePath;
WIN32_FIND_DATA file;
String strPathToSearch = strFilePath;
if (!strPathToSearch.IsEmpty())
strPathToSearch = IncludeTrailingPathDelimiter(strPathToSearch);
HANDLE hFile = FindFirstFile((strPathToSearch + "*").c_str(), &file);
if (hFile != INVALID_HANDLE_VALUE)
{
do
{
String strTheNameOfTheFile = file.cFileName;
// It could be a directory we are looking at
// if so look into that dir
if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if ((strTheNameOfTheFile != ".") && (strTheNameOfTheFile != "..") && (bRecursive))
{
strFoundFilePath = SearchDrive(strFile, strPathToSearch + strTheNameOfTheFile, bRecursive, bStopWhenFound);
if (!strFoundFilePath.IsEmpty() && bStopWhenFound)
break;
}
}
else
{
if (strTheNameOfTheFile == strFile)
{
strFoundFilePath = strPathToSearch + strFile;
/// TODO
// ADD TO COLLECTION TYPE
if (bStopWhenFound)
break;
}
}
}
while (FindNextFile(hFile, &file));
FindClose(hFile);
}
return strFoundFilePath;
}
String strFoundFilePath = SearchDrive("file.ext", "C:\\", ...);
UPDATE: An alternative implementation of SearchDrive()
that does not keep multiple search handles open while recursing through sub-directories:
#include <memory>
String Copy::SearchDrive(const String& strFile, const String& strFilePath, const bool& bRecursive, const bool& bStopWhenFound) const
{
String strFoundFilePath;
WIN32_FIND_DATA file;
String strPathToSearch = strFilePath;
if (!strPathToSearch.IsEmpty())
strPathToSearch = IncludeTrailingPathDelimiter(strPathToSearch);
HANDLE hFile = FindFirstFile((strPathToSearch + "*").c_str(), &file);
if (hFile != INVALID_HANDLE_VALUE)
{
std::auto_ptr<TStringList> subDirs;
do
{
String strTheNameOfTheFile = file.cFileName;
// It could be a directory we are looking at
// if so look into that dir
if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if ((strTheNameOfTheFile != ".") && (strTheNameOfTheFile != "..") && (bRecursive))
{
if (subDirs.get() == NULL)
subDirs.reset(new TStringList);
subDirs->Add(strPathToSearch + strTheNameOfTheFile);
}
}
else
{
if (strTheNameOfTheFile == strFile)
{
strFoundFilePath = strPathToSearch + strFile;
/// TODO
// ADD TO COLLECTION TYPE
if (bStopWhenFound)
break;
}
}
}
while (FindNextFile(hFile, &file));
FindClose(hFile);
if (!strFoundFilePath.IsEmpty() && bStopWhenFound)
return strFoundFilePath;
if (subDirs.get() != NULL)
{
for (int i = 0; i < subDirs->Count; ++i)
{
strFoundFilePath = SearchDrive(strFile, subDirs->Strings[i], bRecursive, bStopWhenFound);
if (!strFoundFilePath.IsEmpty() && bStopWhenFound)
break;
}
}
}
return strFoundFilePath;
}
Upvotes: 10
Reputation:
Your condition is incorrect, you should compare to to INVALID_HANDLE_VALUE
if ( hFile != INVALID_HANDLE_VALUE)
Besides you skip the first matching file returned by FindFirstFile
, is that what you want?
Also I believe you need a wildcard c:\\*
otherwise it will only match c:\\
itself
hFile = FindFirstFile("C:\\*", &file);
Upvotes: 3