Archived

This topic is now archived and is closed to further replies.

Xero-X2

Scanning harddrives (Order problem)

Recommended Posts

I have writtin a function that will scan thought all directories and sub directories and record all files into a big text file. later it will be used to look for files of a certain type. like *.bmp.. but for the moment it finds every thing. I useed FindNextFile/FindFirstFile. it works great except for one problem, when it comes to scanning each drive, the order in which I scan them will cause problems
c:\ works
d:\ fails
e:\ fails
_________
c:\ works
e:\ fails
d:\ fails
_________
d:\ works
c:\ works
e:\ fails
_________
d:\ works
e:\ fails
c:\ works

but

e:\ works
d:\ works
c:\ works
 
why would I have to scan the drives in reverse order? why can''t i scan from c:\ down to the last drive? can anyone lend me some insight into this problem? "I seek knowledge and to help those who also seek it"

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
http://www.chiark.greenend.org.uk/~sgtatham/bugs.html

Share this post


Link to post
Share on other sites
What? Im saying that I can only scan the drives in reverse order, if I try forward order it gives me the error ERROR_FILE_NOT_FOUND. but when I do it backwards it gives no errors and succsessfully compiles the list.

Does anyone know what could cause this?

Share this post


Link to post
Share on other sites
AP is trying to say you did not give enough information. You should post some code so we can see how you are calling FindNextFile. But, I understand your question. There are bugs with FindNextFile especially in how it deals with long filenames. Sorry I don''t know the exact nature of the bugs, but they can cause FindNextFile can return ERROR_FILE_NOT_FOUND for no apparent reason sometimes. You should not check for ERROR_FILE_NOT_FOUND when using FindNextFile. Just check to see if it returns a non zero value (this is in the MSDN docs). But, I am just guessing since I don''t know how you actually have it coded.

Share this post


Link to post
Share on other sites


UINT dirs;
UINT files;


void Scan(char* Dir)
{
WIN32_FIND_DATA data;
HANDLE Hdir= FindFirstFile(Dir,&data);

for (int s=0; s<260; s++)
if (Dir[s]==''*'' || Dir[s]==''.'')
Dir[s]=0;

char addFiles[260];

if (Hdir != INVALID_HANDLE_VALUE)
{
if (data.cFileName[0] != ''.'')
if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
dirs++;
sprintf(addFiles,"%s%s\\*.*",Dir,data.cFileName);
Scan(addFiles);
}
else
{
files++;
}
}
else
{
FindClose(Hdir);
return;
}


while (1)
{
if (FindNextFile(Hdir,&data))
{
if (data.cFileName[0] != ''.'')
if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
dirs++;
sprintf(addFiles,"%s%s\\*.*",Dir,data.cFileName);
Scan(addFiles);
}
else
{
files++;
}

}
else
break;

}

FindClose(Hdir);
}


that is the code that scans and records total dirs, and files.
I run it based each drive

Scan("C:\\*.*");
Scan("D:\\*.*");
Scan("E:\\*.*");


It won''t read a drive that comes after one that is already read.
and it won''t read the same drive twice.

Any help would be appretaited.

"I seek knowledge and to help those who also seek it"

Share this post


Link to post
Share on other sites
I doubt your problem is related to bugs in Find* functions. You can try my code if you'd like:

#include <windows.h>
#include <crtdbg.h>
#include <tchar.h>
#include <string>
#include <queue>
#include <iostream>

// Macros so we can use both MBCS and UNICODE
#ifdef _UNICODE
typedef std::wstring String;
#define Cout std::wcout
#else
typedef std::string String;
#define Cout std::cout
#endif

#ifdef _DEBUG
#define _VERIFY _ASSERT
#else
#define _VERIFY(x) (x)
#endif


static DWORD g_count = 0;

static void OnFoundFile(const String& currentRoot, const WIN32_FIND_DATA& FindData)
{
// Cout << currentRoot << _T('\\') << FindData.cFileName << std::endl;
++g_count;
}

static void WalkPath(LPCTSTR szRootDir, LPCTSTR szSearchPattern)
{
// We do an iterative algorithm, therefore we keep a queue
// of directories to search through. We looop through
// everything we find. If we find a directory, add it
// to that queue.
// Then all we need to do is to keep searching directories
// until that queue is empty, in which case we're ready.
// Seed in the queue is the directory the user gave to
// this function.
std::queue DirectoriesToWalk;
DirectoriesToWalk.push(szRootDir);

// Used for FindFirstFile, re-use the string for performance
String FileName;

while ( !DirectoriesToWalk.empty() )
{
// take a directory to search from the queue
const String CurrentRoot = DirectoriesToWalk.front();
DirectoriesToWalk.pop();

FileName.clear();
FileName += CurrentRoot;
FileName += szSearchPattern;

WIN32_FIND_DATA FindData;
HANDLE hFind = ::FindFirstFile(FileName.c_str(), &FindData);
BOOL Continue = (hFind != INVALID_HANDLE_VALUE);

while (Continue)
{
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (FindData.cFileName[0] != _T('.'))
{
// We found another directory, add it to the pile
// of directories to search through.
std::string DirToAdd(CurrentRoot);
DirToAdd += FindData.cFileName;
DirToAdd += _T('\\');
// Cout << "Adding dir to search: " << DirToAdd << std::endl;
DirectoriesToWalk.push(DirToAdd);
}
}
else
{
// This wasn't a directory.
OnFoundFile(CurrentRoot, FindData);
}

// See if there's anything left in here.
Continue = FindNextFile(hFind, &FindData);
}

if (hFind != INVALID_HANDLE_VALUE)
{
_VERIFY(FindClose(hFind));
}
}
}

void _tmain()
{
WalkPath( _T("C:\\Temp\\"), _T("*") );
Cout << "Number of files: " << g_count << std::endl;
}


[edited by - developer on August 7, 2003 6:37:43 PM]

Share this post


Link to post
Share on other sites