Click to See Complete Forum and Search --> : C++ Directory and File Listing Examples...?


ricky_k6
September 18th, 2005, 01:32 PM
Hi
Now that school is done I have some free time and can actually start
learning the stuff that i'd like to know ;)
I was wondering if any of you could post some examples for things like
- reading in the names of all the files and subdirectories in a directory
- printing the current directory name
- printing file sizes
- Searching for a file ina given directory
Also, i'd be interested in hearing of any books on stuff like this that you would recomend
thanks

BR, ricky

Ejaz
September 18th, 2005, 01:52 PM
Take a look at the following FAQs.

Windows SDK File System: How to check for the existance of a directory/file? (http://www.codeguru.com/forum/showthread.php?t=330024)
Windows SDK File System: How to search for files in a directory and subdirectories? (http://www.codeguru.com/forum/showthread.php?t=312461)
Windows SDK File System: How to count files within a directory and subdirectories? (http://www.codeguru.com/forum/showthread.php?t=312458)

ricky_k6
September 18th, 2005, 02:43 PM
thank you!
I checked all those links. The second link :
Windows SDK File System: How to search for files in a directory and subdirectories?
I have copied the code in this link and compiled and executed in Dec-C++.
It was compiled without any problems, but when I executed it, no result, except blank screen. Actually I did put some "avi" and "txt" files in c drive.

Ejaz
September 18th, 2005, 02:55 PM
Last time I used this code, it worked like a charm. Its hard to figure out the probelm with out going through the code. Please post the actual code you are using.

Smasher/Devourer
September 18th, 2005, 03:02 PM
thank you!
I checked all those links. The second link :
Windows SDK File System: How to search for files in a directory and subdirectories?
I have copied the code in this link and compiled and executed in Dec-C++.
It was compiled without any problems, but when I executed it, no result, except blank screen. Actually I did put some "avi" and "txt" files in c drive.
Chances are that you've got tons of files and directories on that drive and the program is just taking a very long time to execute; it doesn't report any results until it's found them all, and there's no progress indicator or anything like that while the search is running. If you want to see an example of it running more quickly, replace "c:" in the call to SearchDirectory() with the name of a directory with few or no subdirectories to search. For example, something like:
iRC = SearchDirectory(vecAviFiles, "E:\\Video\\Movies", "avi");
Don't forget the need for the double-backslash escape sequence to separate directories. It's obvious, but I forgot to do it while testing that code. :blush:

ricky_k6
September 18th, 2005, 03:30 PM
hi! thank you for both!

Yes it was the reason, i got result after 5 minutes, thank a lot!

ricky_k6
September 19th, 2005, 09:33 AM
After I got the search results, I want findout file size and date/time for the latest changes of the file...
How can I get those results?

golanshahar
September 19th, 2005, 09:38 AM
After I got the search results, I want findout file size and date/time for the latest changes of the file...
How can I get those results?


::GetFileSize(..) (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/getfilesize.asp)
::GetFileTime(..) (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getfiletime.asp)


Cheers

ricky_k6
September 19th, 2005, 10:47 AM
hi!

I am new to this area, I cannot use those functions in my code. I am pasting the code here. Can u suggest me how to use those functions in the followin g code, so I can disply file name, size and last modified date on the screen. Thank you

----------------CODE------------------------
#include <string>
#include <vector>
#include <iostream>

#include <windows.h>
#include <conio.h>

int SearchDirectory(std::vector<std::string> &refvecFiles,
const std::string &refcstrRootDirectory,
const std::string &refcstrExtension,
bool bSearchSubdirectories = true)
{
std::string strFilePath; // Filepath
std::string strPattern; // Pattern
std::string strExtension; // Extension
HANDLE hFile; // Handle to file
WIN32_FIND_DATA FileInformation; // File information


strPattern = refcstrRootDirectory + "\\*.*";

hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation);
if(hFile != INVALID_HANDLE_VALUE)
{
do
{
if(FileInformation.cFileName[0] != '.')
{
strFilePath.erase();
strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;

if(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if(bSearchSubdirectories)
{
// Search subdirectory
int iRC = SearchDirectory(refvecFiles,
strFilePath,
refcstrExtension,
bSearchSubdirectories);
if(iRC)
return iRC;
}
}
else
{
// Check extension
strExtension = FileInformation.cFileName;
strExtension = strExtension.substr(strExtension.rfind(".") + 1);

if(strExtension == refcstrExtension)
{
// Save filename
refvecFiles.push_back(strFilePath);
}
}
}
} while(::FindNextFile(hFile, &FileInformation) == TRUE);

// Close handle
::FindClose(hFile);

DWORD dwError = ::GetLastError();
if(dwError != ERROR_NO_MORE_FILES)
return dwError;
}

return 0;
}


int main()
{
int iRC = 0;
std::vector<std::string> vecAviFiles;
std::vector<std::string> vecTxtFiles;


// Search 'C:/Program Files/BitComet/Downloads' for '.avi' files including subdirectories
iRC = SearchDirectory(vecAviFiles, "C://Program Files/BitComet/Downloads", "avi");
if(iRC)
{
std::cout << "Error " << iRC << std::endl;
return -1;
}

// Print results
for(std::vector<std::string>::iterator iterAvi = vecAviFiles.begin();
iterAvi != vecAviFiles.end();
++iterAvi)
{
std::cout << *iterAvi << std::endl;
}

// Search 'c:\textfiles' for '.txt' files excluding subdirectories
iRC = SearchDirectory(vecTxtFiles, "c:\\textfiles", "txt", false);
if(iRC)
{
std::cout << "Error " << iRC << std::endl;
return -1;
}

// Print results
for(std::vector<std::string>::iterator iterTxt = vecTxtFiles.begin();
iterTxt != vecTxtFiles.end();
++iterTxt)
std::cout << *iterTxt << std::endl;

// Wait for keystroke
_getch();

return 0;
}
----------------END OF CODE------------------------

golanshahar
September 19th, 2005, 11:51 AM
first PLEASE use code tag its really HARD to look on a code like this.

now to the question in the function SearchDirectory(..) when you running on all the files before pushing_back the file name to the vector you have the HANDLE to the file so you can easily check the size and times via the functions i posted you above.


:
:
if(strExtension == refcstrExtension)
{
// Save filename
refvecFiles.push_back(strFilePath);

// Get file size
DWORD FileSizeHigh= 0;
DWORD FileSize = ::GetFileSize(hFile,&FileSizeHigh);

// get file times
FILETIME ftCreattion={0};
FILETIME ftLastAccess={0};
FILETIME ftLastWrite={0};

::GetFileTime(hFile,&ftCreattion,&ftLastAccess,&ftLastWrite);
// do something with times and size

}
:
:


regurding the file size just note:

If the function succeeds, the return value is the low-order doubleword of the file size, and, if lpFileSizeHigh is non-NULL, the function puts the high-order doubleword of the file size into the variable pointed to by that parameter.


Cheers

ovidiucucu
September 19th, 2005, 12:10 PM
To ricky_k6,

I have added CODE tags to your post as golanshahar suggested. Now it's a little bit more readable.
Please, take a look at vB Codes (http://www.codeguru.com/forum/misc.php?do=bbcode).

Regards,
Ovidiu

ricky_k6
September 20th, 2005, 05:34 AM
thank you for both.

I have used the code that u suggested, and it was compiled wiothout any problem. But when I try to run it the system gives a STRANGE error.

The ERROR:

The instrucion at "0x77e207a1" referenced memory at "0x00402730". The memory could not be "written"

And the execution is terminated. What can be the wrong.

And I want to printout the FWORD , FILETIME to the screen, can i use "cout" statement.

thank you..

golanshahar
September 20th, 2005, 05:42 AM
thank you for both.

Your welcome :)


I have used the code that u suggested, and it was compiled wiothout any problem. But when I try to run it the system gives a STRANGE error.

The ERROR:

The instrucion at "0x77e207a1" referenced memory at "0x00402730". The memory could not be "written"

And the execution is terminated. What can be the wrong.


well fisrt you need to check on which function it is happening, and of course try to do it in debug mode so you will see why? maybe the HANDLE to the file is not vaild :confused: it something you need to check in debug mode.


And I want to printout the FWORD , FILETIME to the screen, can i use "cout" statement.


yes you will see a big integer number ;) but yes you can.

Cheers

ricky_k6
September 20th, 2005, 06:07 AM
small mistake by myself. your code was working fine.

When I try to printout ftLastWrite using cout, it says it is giving erros that operator << is not overloaded.

SO I googled, and I found some useful info to printout ftLastWrite.



FileTimeToSystemTime(&ftLastWrite, &stUTC);
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);

//std::cout<<"The last modified time"<<ftLastWrite<<std::endl;
std::cout<<"The file size is"<<FileSize<<std::endl;

// Build a string showing the date and time.
wsprintf(lpszString, TEXT("%02d/%02d/%d %02d:%02d"),
stLocal.wMonth, stLocal.wDay, stLocal.wYear,
stLocal.wHour, stLocal.wMinute);
std::cout<<"in write time function "<<lpszString<<std::endl;


I tried the above code. The system gives error



The instrucion at "0x77e207a1" referenced memory at "0x00402730". The memory could not be "written"


All I just need is to printout the file size and last modified date on the screen in a readable manner.

Any suggestions?

Thank you.

NoHero
September 20th, 2005, 06:53 AM
Use the debugger to find out where exactly this runtime error occurs.

ricky_k6
September 20th, 2005, 07:06 AM
The error occurs at the following function


wsprintf(lpszString, TEXT("%02d/%02d/%d %02d:%02d"),
stLocal.wMonth, stLocal.wDay, stLocal.wYear,
stLocal.wHour, stLocal.wMinute);
std::cout<<"in write time function "<<lpszString<<std::endl;



I just need is to printout the file size and last modified date on the screen in a readable manner.

Any suggestions?

Thank you.

For your convinience I am pasting the whole code:

#include <string>
#include <vector>
#include <iostream>

#include <windows.h>
#include <conio.h>


int SearchDirectory(std::vector<std::string> &refvecFiles,
const std::string &refcstrRootDirectory,
const std::string &refcstrExtension,
bool bSearchSubdirectories = true)
{
std::string strFilePath; // Filepath
std::string strPattern; // Pattern
std::string strExtension; // Extension
HANDLE hFile; // Handle to file
WIN32_FIND_DATA FileInformation; // File information


strPattern = refcstrRootDirectory + "\\*.*";

hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation);
if(hFile != INVALID_HANDLE_VALUE)
{
do
{
if(FileInformation.cFileName[0] != '.')
{
strFilePath.erase();
strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;

if(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if(bSearchSubdirectories)
{
// Search subdirectory
int iRC = SearchDirectory(refvecFiles,
strFilePath,
refcstrExtension,
bSearchSubdirectories);
if(iRC)
return iRC;
}
}
else
{
// Check extension
strExtension = FileInformation.cFileName;
strExtension = strExtension.substr(strExtension.rfind(".") + 1);
//std::cout<<"strExtension"<<std::endl;

if(strExtension == refcstrExtension)
{
//FILETIME ftCreation, ftLastAccess, ftLastWrite;
SYSTEMTIME stUTC, stLocal;

// Save filename
refvecFiles.push_back(strFilePath);
refvecFiles.push_back(strFilePath);

// Get file size
DWORD FileSizeHigh= 0;
DWORD FileSize = ::GetFileSize(hFile,&FileSizeHigh);

// get file times
FILETIME ftCreattion={0};
FILETIME ftLastAccess={0};
FILETIME ftLastWrite={0};
LPTSTR lpszString;

::GetFileTime(hFile,&ftCreattion,&ftLastAccess,&ftLastWrite);

FileTimeToSystemTime(&ftLastWrite, &stUTC);
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);

std::cout<<"The last modified time"<<ftLastWrite<<std::endl;
std::cout<<"The file size is"<<FileSize<<std::endl;

Build a string showing the date and time.
wsprintf(lpszString, TEXT("%02d/%02d/%d %02d:%02d"),
stLocal.wMonth, stLocal.wDay, stLocal.wYear,
stLocal.wHour, stLocal.wMinute);
std::cout<<"The last modified time (Local time)"<<lpszString<<std::endl;

}
}
}
} while(::FindNextFile(hFile, &FileInformation) == TRUE);

// Close handle
::FindClose(hFile);

DWORD dwError = ::GetLastError();
if(dwError != ERROR_NO_MORE_FILES)
return dwError;
}

return 0;
}


int main()
{
int iRC = 0;
std::vector<std::string> vecAviFiles;
std::vector<std::string> vecTxtFiles;

//std::cout<<"hello"<<std::endl;

// Search 'c:' for '.avi' files including subdirectories
iRC = SearchDirectory(vecAviFiles, "C://Program Files/BitComet/Downloads", "avi");
if(iRC)
{
std::cout << "Error " << iRC << std::endl;
return -1;
}

// Print results
for(std::vector<std::string>::iterator iterAvi = vecAviFiles.begin();
iterAvi != vecAviFiles.end();
++iterAvi)
{
std::cout << *iterAvi << std::endl;
std::cout<<"in for loop"<<std::endl;
}

// Search 'c:\textfiles' for '.txt' files excluding subdirectories
iRC = SearchDirectory(vecTxtFiles, "c:\\textfiles", "txt", false);
if(iRC)
{
std::cout << "Error " << iRC << std::endl;
return -1;
}

// Print results
for(std::vector<std::string>::iterator iterTxt = vecTxtFiles.begin();
iterTxt != vecTxtFiles.end();
++iterTxt)
std::cout << *iterTxt << std::endl;

// Wait for keystroke
_getch();

return 0;
}

golanshahar
September 20th, 2005, 12:46 PM
the bug you have is because you are using wsprintf(..) to a uninitialized pointer!


LPTSTR lpszString;

wsprintf(lpszString, TEXT("%02d/%02d/%d %02d:%02d"),....);



either use new and then delete or simple declare it on the stack like this:


char lpszString[MAX_PATH]={0};


Cheers

ricky_k6
September 20th, 2005, 08:46 PM
hi!

yeah, that was the problem. Thank you!

I want to use wildcards *, ? in the file search program.

Are there any library function for comparing strings with file names. I want to emplementing searching, that supposrts wild card. Just same as windows file search. Any suggestions??

than k you!

Ricky.

golanshahar
September 21st, 2005, 02:21 AM
hi!

yeah, that was the problem. Thank you!


Your welcome. :)


I want to use wildcards *, ? in the file search program.

Are there any library function for comparing strings with file names. I want to emplementing searching, that supposrts wild card. Just same as windows file search. Any suggestions??


i dont really understand whats the problem if you will deliver "*.*" in the ::FindFirstFile(..)/::FindNextFile(..) it should be ok. and according to your code you are doing it...so you are using the wildchars....:confused:

Cheers

ricky_k6
September 21st, 2005, 09:15 AM
No, I cannot use wildcards in my program. I ampasting the ocde, and in the main function I used wildcards, the code where I used wildcard is enclipsed by "//////////////////////////////////"
Is there any thing wroing....



#include <string>
#include <vector>
#include <iostream>

#include <windows.h>
#include <conio.h>


int SearchDirectory(std::vector<std::string> &refvecFiles,
const std::string &refcstrRootDirectory,
const std::string &refcstrExtension,
bool bSearchSubdirectories = true)
{
std::string strFilePath; // Filepath
std::string strPattern; // Pattern
std::string strExtension; // Extension
HANDLE hFile; // Handle to file
WIN32_FIND_DATA FileInformation; // File information


strPattern = refcstrRootDirectory + "\\*.*";

hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation);
if(hFile != INVALID_HANDLE_VALUE)
{
do
{
if(FileInformation.cFileName[0] != '.')
{
strFilePath.erase();
strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;

if(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if(bSearchSubdirectories)
{
// Search subdirectory
int iRC = SearchDirectory(refvecFiles,
strFilePath,
refcstrExtension,
bSearchSubdirectories);
if(iRC)
return iRC;
}
}
else
{
// Check extension
strExtension = FileInformation.cFileName;
strExtension = strExtension.substr(strExtension.rfind(".") + 1);
//std::cout<<"strExtension"<<std::endl;

if(strExtension == refcstrExtension)
{
//FILETIME ftCreation, ftLastAccess, ftLastWrite;
SYSTEMTIME stUTC, stLocal;

// Save filename
refvecFiles.push_back(strFilePath);
refvecFiles.push_back(strFilePath);

// Get file size
DWORD FileSizeHigh= 0;
DWORD FileSize = ::GetFileSize(hFile,&FileSizeHigh);

// get file times
FILETIME ftCreattion={0};
FILETIME ftLastAccess={0};
FILETIME ftLastWrite={0};
//LPTSTR lpszString;
char lpszString[MAX_PATH]={0};

::GetFileTime(hFile,&ftCreattion,&ftLastAccess,&ftLastWrite);

FileTimeToSystemTime(&ftLastWrite, &stUTC);
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);

//std::cout<<"The last modified time"<<ftLastWrite<<std::endl;
std::cout<<"The file size is"<<FileSize<<std::endl;

//Build a string showing the date and time.
wsprintf(lpszString, TEXT("%02d/%02d/%d %02d:%02d"),
stLocal.wMonth, stLocal.wDay, stLocal.wYear,
stLocal.wHour, stLocal.wMinute);
std::cout<<"The last modified time (Local time)"<<lpszString<<std::endl;

}
}
}
} while(::FindNextFile(hFile, &FileInformation) == TRUE);

// Close handle
::FindClose(hFile);

DWORD dwError = ::GetLastError();
if(dwError != ERROR_NO_MORE_FILES)
return dwError;
}

return 0;
}


int main()
{
int iRC = 0;
std::vector<std::string> vecAviFiles;
std::vector<std::string> vecTxtFiles;

//std::cout<<"hello"<<std::endl;

// Search 'c:' for '.*' files including subdirectories
///////////////////////////////////////////////////////////////////////////////////////////////
iRC = SearchDirectory(vecAviFiles, "C://Program Files/BitComet/Downloads","*" );
///////////////////////////////////////////////////////////////////////////////////////////////
if(iRC)
{
std::cout << "Error " << iRC << std::endl;
return -1;
}

// Print results
for(std::vector<std::string>::iterator iterAvi = vecAviFiles.begin();
iterAvi != vecAviFiles.end();
++iterAvi)
{
std::cout << *iterAvi << std::endl;
std::cout<<"in for loop"<<std::endl;
}

// Search 'c:\textfiles' for '.txt' files excluding subdirectories
iRC = SearchDirectory(vecTxtFiles, "c:\\textfiles", "txt", false);
if(iRC)
{
std::cout << "Error " << iRC << std::endl;
return -1;
}

// Print results
for(std::vector<std::string>::iterator iterTxt = vecTxtFiles.begin();
iterTxt != vecTxtFiles.end();
++iterTxt)
std::cout << *iterTxt << std::endl;

// Wait for keystroke
_getch();

return 0;
}

golanshahar
September 21st, 2005, 09:54 AM
ok i understood your problem the function SearchDirectory(..) is getting :

the vector to which is pushing all find files
root directory to start to look from
and the extention of the file you want to look for!!!


now the fuction itself uses a wlidcard to look for all files in the directories here is the pattern it looks for:

strPattern = refcstrRootDirectory + "\\*.*";


each file that is being reached is being checked if he matches the extention the function got:

if(strExtension == refcstrExtension)


now your problem is that you are sending * as extention

iRC = SearchDirectory(vecAviFiles, "C://Program Files/BitComet/Downloads","*");

and since files dont have .* extention the above if never become true.

now its depend what you want?
if you want to get all the files that the function run into, you need to modify the function a little bit and put comment on that if, this will return you all the files.
if you want to look for particular files you also need to change the function so it will get list of extentions and not just one.

one thing for sure you cant pass * ;)

Cheers

ricky_k6
September 21st, 2005, 12:52 PM
if you want to get all the files that the function run into, you need to modify the function a little bit and put comment on that if, this will return you all the files.
if you want to look for particular files you also need to change the function so it will get list of extentions and not just one.


I want both :)
- All the files that function run into
- particular files you with list of extentions and not just one...

Just like windows search... Is it difficult task? Any hints or suggestion... If you can, can you explain with example code?

thank you!

golanshahar
September 21st, 2005, 01:27 PM
here i did it for you - i didnt test it too much ;) but its should work

if you will pass empty vector it will return all files, if you want couple extentions you need to push them to the vector


#include <string>
#include <vector>
#include <iostream>

#include <windows.h>
#include <conio.h>

void AddFile (std::vector<std::string> &refvecFiles ,
const std::string strFilePath ,
const HANDLE hFile)
{
//FILETIME ftCreation, ftLastAccess, ftLastWrite;
SYSTEMTIME stUTC, stLocal;

// Save filename
refvecFiles.push_back(strFilePath);
refvecFiles.push_back(strFilePath);

// Get file size
DWORD FileSizeHigh= 0;
DWORD FileSize = ::GetFileSize(hFile,&FileSizeHigh);

// get file times
FILETIME ftCreattion={0};
FILETIME ftLastAccess={0};
FILETIME ftLastWrite={0};
//LPTSTR lpszString;
char lpszString[MAX_PATH]={0};

::GetFileTime(hFile,&ftCreattion,&ftLastAccess,&ftLastWrite);

FileTimeToSystemTime(&ftLastWrite, &stUTC);
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);

//std::cout<<"The last modified time"<<ftLastWrite<<std::endl;
std::cout<<"The file size is"<<FileSize<<std::endl;

//Build a string showing the date and time.
wsprintf(lpszString, TEXT("%02d/%02d/%d %02d:%02d"),
stLocal.wMonth, stLocal.wDay, stLocal.wYear,
stLocal.wHour, stLocal.wMinute);
std::cout<<"The last modified time (Local time)"<<lpszString<<std::endl;

}

int SearchDirectory(std::vector<std::string> &refvecFiles,
const std::string &refcstrRootDirectory,
const std::vector<std::string> &refcstrExtension,
bool bSearchSubdirectories = true)
{
std::string strFilePath; // Filepath
std::string strPattern; // Pattern
std::string strExtension; // Extension
HANDLE hFile; // Handle to file
WIN32_FIND_DATA FileInformation; // File information


strPattern = refcstrRootDirectory + "\\*.*";

hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation);
if(hFile != INVALID_HANDLE_VALUE)
{
do
{
if(FileInformation.cFileName[0] != '.')
{
strFilePath.erase();
strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;

if(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if(bSearchSubdirectories)
{
// Search subdirectory
int iRC = SearchDirectory( refvecFiles,
strFilePath,
refcstrExtension,
bSearchSubdirectories);
if(iRC)
return iRC;
}
}
else
{
// Check extension
strExtension = FileInformation.cFileName;
strExtension = strExtension.substr(strExtension.rfind(".") + 1);
//std::cout<<"strExtension"<<std::endl;

if ( refcstrExtension.size() == 0 ) // all files wanted
AddFile(refvecFiles,strFilePath,hFile);
else // look for extentions
{
for ( int k=0;k<refcstrExtension.size();k++)
{
if(strExtension == refcstrExtension[k]) // check all extention list
{
AddFile(refvecFiles,strFilePath,hFile);
}
}
}
}
}
} while(::FindNextFile(hFile, &FileInformation) == TRUE);

// Close handle
::FindClose(hFile);

DWORD dwError = ::GetLastError();
if(dwError != ERROR_NO_MORE_FILES)
return dwError;
}

return 0;
}


int main()
{
int iRC = 0;
std::vector<std::string> vecAviFiles;
std::vector<std::string> vecTxtFiles;

//std::cout<<"hello"<<std::endl;

// sreach for those extentions
std::vector<std::string> Ext;
Ext.push_back("exe");
Ext.push_back("bat");
Ext.push_back("doc");

iRC = SearchDirectory(vecAviFiles, "C://Program Files/",Ext);
if(iRC)
{
std::cout << "Error " << iRC << std::endl;
return -1;
}

// Print results
for(std::vector<std::string>::iterator iterAvi = vecAviFiles.begin();
iterAvi != vecAviFiles.end();
++iterAvi)
{
std::cout << *iterAvi << std::endl;
std::cout<<"in for loop"<<std::endl;
}

std::vector<std::string> ExtEmpty;
// empty vector will get all files
iRC = SearchDirectory(vecTxtFiles, "c:\\",ExtEmpty, false);
if(iRC)
{
std::cout << "Error " << iRC << std::endl;
return -1;
}

// Print results
for(std::vector<std::string>::iterator iterTxt = vecTxtFiles.begin();
iterTxt != vecTxtFiles.end();
++iterTxt)
std::cout << *iterTxt << std::endl;

// Wait for keystroke
_getch();

return 0;
}


Cheers

ricky_k6
September 22nd, 2005, 06:29 PM
Dont know how to say thank you to you...
but I am greatful to you... thank you

golanshahar
September 23rd, 2005, 06:17 AM
Dont know how to say thank you to you...
but I am greatful to you... thank you

you just said it ;)

You are welcome :wave:

Cheers

ricky_k6
December 23rd, 2005, 09:06 AM
Hi all again!

I have written a program before for searching directories on Disk, but now I found some short commings...

I have file (ricky.txt) in a directory, where I am searching
- The program can find if search string is
*.txt , ricky.txt
- But it cannot find if search string is
ricky, or txt... Like in windows search

The program cannot search the file in sub directories, even if I put the sub directory flag as true

SearchDirectory(vecFiles, strDir, strSearchString, subDir);

I put subDir value as "true", but doesn\t works...

The file size always comming as: 4294967295, which is not actualy file size

Last modified date always comming as 01/01/1601, which is not actual modified date

Can some one help me

Here is the code




------------------------------------------------------

// main.cpp

#include <string>
#include <vector>
#include <iostream>

#include <windows.h>
#include <conio.h>

#include "fileinf.h"

void AddFile (std::vector<FileInf> &refvecFiles ,
const std::string strFilePath ,
const std::string strFileName ,
const HANDLE hFile)
{
SYSTEMTIME stUTC, stLocal;

// Get file size
DWORD FileSizeHigh= 0;
DWORD FileSize = ::GetFileSize(hFile,&FileSizeHigh);

// get file times
FILETIME ftCreattion={0};
FILETIME ftLastAccess={0};
FILETIME ftLastWrite={0};

char lpszString[MAX_PATH]={0};

::GetFileTime(hFile,&ftCreattion,&ftLastAccess,&ftLastWrite);

FileTimeToSystemTime(&ftLastWrite, &stUTC);
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);

//Build a string showing the date and time.
wsprintf(lpszString, TEXT("%02d/%02d/%d %02d:%02d"),
stLocal.wMonth, stLocal.wDay, stLocal.wYear,
stLocal.wHour, stLocal.wMinute);

// Build the FileInf object.
FileInf FI;
FI.setFilePath(strFilePath);
FI.setFileName(strFileName);
FI.setFileSize(FileSize);
FI.setlpszString(lpszString);

// Insert the object into the vector
refvecFiles.push_back(FI);

}

int SearchDirectory(std::vector<FileInf> &refvecFiles,
const std::string &refcstrRootDirectory,
const std::string &refcstrExtension,
bool bSearchSubdirectories = true)
{
std::string strFilePath; // Filepath
std::string strPattern; // Pattern
std::string strExtension; // Extension
HANDLE hFile; // Handle to file
WIN32_FIND_DATA FileInformation; // File information


strPattern = refcstrRootDirectory + "\\"+ refcstrExtension;

hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation);
if(hFile != INVALID_HANDLE_VALUE)
{
do
{
if(FileInformation.cFileName[0] != '.')
{
strFilePath.erase();
strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;

if(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if(bSearchSubdirectories)
{
// Search subdirectory
int iRC = SearchDirectory( refvecFiles,
strFilePath,
refcstrExtension,
bSearchSubdirectories);
if(iRC)
return iRC;
}
}
else
{
AddFile(refvecFiles, strFilePath, FileInformation.cFileName, hFile);
}
}
} while(::FindNextFile(hFile, &FileInformation) == TRUE);

// Close handle
::FindClose(hFile);

DWORD dwError = ::GetLastError();
if(dwError != ERROR_NO_MORE_FILES)
return dwError;
}

return 0;
}


int main()
{
int iRC = 0;
std::vector<FileInf> vecFiles;
std::vector<FileInf> vecTxtFiles;
char option;
int choice;
bool subDir; // include subdirectories?
std::string strDir, strSearchString;

std::cout<<"Enter the search directory (example: C://Dike, use double slash just after the drive)"<<std::endl;
std::cin>>strDir;
std::cout<<"Enter the search string"<<std::endl;
std::cin>>strSearchString;
std::cout<<"Do you want to search in sub directories ? (Y/N)"<<std::endl;
std::cin>>option;


if(option=='Y'||option=='y')
subDir = true;

if(option=='N'||option=='n')
subDir = false;

iRC = SearchDirectory(vecFiles, strDir, strSearchString, subDir);
if(iRC)
{
std::cout << "Error " << iRC << std::endl;
return -1;
}

// Sort the FileInf objects in vecFiles vector


for(std::vector<FileInf>::iterator iterAvi = vecFiles.begin();
iterAvi != vecFiles.end();
++iterAvi)
{
std::cout << "File name :";
std::cout << iterAvi->getFileName()<< std::endl;
std::cout << "Location :";
std::cout << iterAvi->getFilePath()<< std::endl;
std::cout << "The size of file is :";
std::cout << iterAvi->getFileSize()<< std::endl;
std::cout << "Last modified :";
std::cout << iterAvi->getlpszString()<< std::endl<<std::endl;
}

// Wait for keystroke
getch();
return 0;
}

-------------------------

// File FileInf.h

#include <windows.h>
#include <iostream>
#ifndef FileInfH
#define FileInfH

class FileInf
{
private:
std::string filePath; // The file path
std::string fileName; // File name
DWORD fileSize; // File size
char lpszString[MAX_PATH]; // To hold the last date of modification

public:
// Constructor
FileInf();
// Copy constructor
FileInf(const FileInf&);
// Distructor
~FileInf();
// Set functions
void setFilePath(std::string);
void setFileName(std::string);
void setFileSize(DWORD);
void setlpszString(char*);
// Get functions
std::string getFilePath();
std::string getFileName();
DWORD getFileSize();
char* getlpszString();
};

#endif


--------------------------------------




Thank you....

best regards,
Ricky!

golanshahar
December 23rd, 2005, 10:11 AM
couple of things:

you didnt provide the FileInf.cpp hence code cant compile!
regurding the file name to be searched - if you want it to work like windows you should use wildcard! *.* and then you will need to check yourself each file that you run into, so in that case you will be able to find any pattern you want.
about file size, now when i look at it, instead of using the ::GetFileSize(..) you can use the info you getting inside the WIN32_FIND_DATA (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/win32_find_data_str.asp) struct there is all the time info about the file you will need.
about the recursive issue, since this code was taken from the faq i find it hard to beleive that it doesnt work, plus looking at the code it looks just fine and it should work! did you step in debbuger to see why its not working?
maybe this line fails:

hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation);

hence its not workling?


Cheers

ricky_k6
December 23rd, 2005, 10:20 AM
thanks for the reply
here is the whole code!

I used the debugger but there were no errors .....


// main .cpp

#include <string>
#include <vector>
#include <iostream>

#include <windows.h>
#include <conio.h>

#include "fileinf.h"

void AddFile (std::vector<FileInf> &refvecFiles ,
const std::string strFilePath ,
const std::string strFileName ,
const HANDLE hFile)
{
SYSTEMTIME stUTC, stLocal;

// Get file size
DWORD FileSizeHigh= 0;
DWORD FileSize = ::GetFileSize(hFile,&FileSizeHigh);

// get file times
FILETIME ftCreattion={0};
FILETIME ftLastAccess={0};
FILETIME ftLastWrite={0};

char lpszString[MAX_PATH]={0};

::GetFileTime(hFile,&ftCreattion,&ftLastAccess,&ftLastWrite);

FileTimeToSystemTime(&ftLastWrite, &stUTC);
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);

//Build a string showing the date and time.
wsprintf(lpszString, TEXT("%02d/%02d/%d %02d:%02d"),
stLocal.wMonth, stLocal.wDay, stLocal.wYear,
stLocal.wHour, stLocal.wMinute);

// Build the FileInf object.
FileInf FI;
FI.setFilePath(strFilePath);
FI.setFileName(strFileName);
FI.setFileSize(FileSize);
FI.setlpszString(lpszString);

// Insert the object into the vector
refvecFiles.push_back(FI);

}

int SearchDirectory(std::vector<FileInf> &refvecFiles,
const std::string &refcstrRootDirectory,
const std::string &refcstrExtension,
bool bSearchSubdirectories = true)
{
std::string strFilePath; // Filepath
std::string strPattern; // Pattern
std::string strExtension; // Extension
HANDLE hFile; // Handle to file
WIN32_FIND_DATA FileInformation; // File information


strPattern = refcstrRootDirectory + "\\"+ refcstrExtension;

hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation);
if(hFile != INVALID_HANDLE_VALUE)
{
do
{
if(FileInformation.cFileName[0] != '.')
{
strFilePath.erase();
strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;

if(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if(bSearchSubdirectories)
{
// Search subdirectory
int iRC = SearchDirectory( refvecFiles,
strFilePath,
refcstrExtension,
bSearchSubdirectories);
if(iRC)
return iRC;
}
}
else
{
AddFile(refvecFiles, strFilePath, FileInformation.cFileName, hFile);
}
}
} while(::FindNextFile(hFile, &FileInformation) == TRUE);

// Close handle
::FindClose(hFile);

DWORD dwError = ::GetLastError();
if(dwError != ERROR_NO_MORE_FILES)
return dwError;
}

return 0;
}

// This function will be used to sort the FileInf objects according to the file name
bool cmpFileName(FileInf F1, FileInf F2)
{
return F1.getFileName()<F2.getFileName();
}

// This function will be used to sort the FileInf objects according to the file suffix/extention
bool cmpFileSuffix(FileInf F1, FileInf F2)
{
std::string strSuffix1=F1.getFileName();
std::string strSuffix2=F2.getFileName();
strSuffix1 = strSuffix1.substr(strSuffix1.rfind(".") + 1);
strSuffix2 = strSuffix2.substr(strSuffix2.rfind(".") + 1);
return strSuffix1<strSuffix2;
}

// This function will be used to sort the FileInf objects according to the catalog
bool cmpDirectory(FileInf F1, FileInf F2)
{
return F1.getFilePath() < F2.getFilePath();
}

// This function will be used to sort the FileInf objects according to the size
bool cmpFileSize(FileInf F1, FileInf F2)
{
return F1.getFileSize()<F2.getFileSize();
}


int main()
{
int iRC = 0;
std::vector<FileInf> vecFiles;
std::vector<FileInf> vecTxtFiles;
char option;
int choice;
bool subDir; // include subdirectories?
std::string strDir, strSearchString;

std::cout<<"Enter the search directory (example: C://Dike, use double slash just after the drive)"<<std::endl;
std::cin>>strDir;
std::cout<<"Enter the search string"<<std::endl;
std::cin>>strSearchString;
std::cout<<"Do you want to search in sub directories ? (Y/N)"<<std::endl;
option = getch();
std::cout<<option<<std::endl;
std::cout<<"How do you want to display the result"<<std::endl;
std::cout<<"1. Sorted by file name, 2. Sorted by File suffix, 3. sortyed by catalog, 4. Sorted by file size "<<std::endl;
std::cin>>choice;


if(option=='Y'||option=='y')
subDir = true;

if(option=='N'||option=='n')
subDir = false;

iRC = SearchDirectory(vecFiles, strDir, strSearchString, subDir);
if(iRC)
{
std::cout << "Error " << iRC << std::endl;
return -1;
}

// Sort the FileInf objects in vecFiles vector

switch(choice)
{
// Sort the FileInf objects in vecFiles vector according to file names
case 1:
sort(vecFiles.begin(), vecFiles.end(), cmpFileName);
break;
// Sort the FileInf objects in vecFiles vector according to file suffix/extention
case 2:
sort(vecFiles.begin(), vecFiles.end(), cmpFileSuffix);
break;
// Sort the FileInf objects in vecFiles vector according to catalog
case 3:
sort(vecFiles.begin(), vecFiles.end(), cmpDirectory);
break;
// Sort the FileInf objects in vecFiles vector according to file size
case 4:
sort(vecFiles.begin(), vecFiles.end(), cmpFileSize);
break;
default:
std::cout<<"You entered invalid choice, the files will be displayed in order as they found"<<std::endl;
}

for(std::vector<FileInf>::iterator iterAvi = vecFiles.begin();
iterAvi != vecFiles.end();
++iterAvi)
{
std::cout << "File name :";
std::cout << iterAvi->getFileName()<< std::endl;
std::cout << "Location :";
std::cout << iterAvi->getFilePath()<< std::endl;
std::cout << "The size of file is :";
std::cout << iterAvi->getFileSize()<< std::endl;
std::cout << "Last modified :";
std::cout << iterAvi->getlpszString()<< std::endl<<std::endl;
}

// Wait for keystroke
getch();
return 0;
}

// ------------------- end of main.cpp

---------------------------

// file fileinf.h

#include <windows.h>
#include <iostream>
#ifndef FileInfH
#define FileInfH

class FileInf
{
private:
std::string filePath; // The file path
std::string fileName; // File name
DWORD fileSize; // File size
char lpszString[MAX_PATH]; // To hold the last date of modification

public:
// Constructor
FileInf();
// Copy constructor
FileInf(const FileInf&);
// Distructor
~FileInf();
// Set functions
void setFilePath(std::string);
void setFileName(std::string);
void setFileSize(DWORD);
void setlpszString(char*);
// Get functions
std::string getFilePath();
std::string getFileName();
DWORD getFileSize();
char* getlpszString();
};

#endif

// ------------------- end of fileinf.h
---------------------

// file fileinf.cpp

#include <windows.h>
#include <iostream>
#include "fileinf.h"

// definition of Constructor
FileInf :: FileInf()
{}

// definition of Copy constructor
FileInf :: FileInf(const FileInf& rhs)
{
fileName = rhs.fileName;
fileSize = rhs.fileSize;
std::strcpy(lpszString, rhs.lpszString);
}

// Definition of set functions
void FileInf::setFilePath(std::string tmpFilePath)
{
filePath = tmpFilePath;
}

void FileInf::setFileName(std::string tmpFileName)
{
fileName = tmpFileName;
}

void FileInf::setFileSize(DWORD tmpFileSize)
{
fileSize=tmpFileSize;
}

void FileInf::setlpszString(char* tmpLpszString)
{
strcpy(lpszString, tmpLpszString);
}

// Definition of get functions
std::string FileInf::getFilePath()
{
return filePath;
}

std::string FileInf::getFileName()
{
return fileName;
}

DWORD FileInf::getFileSize()
{
return fileSize;
}

char* FileInf::getlpszString()
{
return lpszString;
}

// DEfinition of destructor
FileInf :: ~FileInf()
{
}

// ------------------- end of fileinf.cpp

golanshahar
December 23rd, 2005, 12:26 PM
thanks for the reply
here is the whole code!

I used the debugger but there were no errors .....


its weird that you say you checkced it and there are no errors :confused:

why its weird?


that code doesnt compile!

error C2039: 'strcpy' : is not a member of 'std'

anyway after fixing it, i ran the code.
now you say no errors? well like i told you before the ::FindFirstFile(..) fails thats why you dont get to the recursive at all.
why its fails? cause if you looking for a file that is in the subfolder then since you dont use wildcards (what i told you 10 times already :rolleyes: ) it fails and exit the function. you can look in debbuger yourself and see.


anyway use wildcard and about the other issues read my previous post.

Cheers

ricky_k6
December 31st, 2005, 10:55 AM
thanks a lot golashankar!

WIN32_FIND_DATA works pretty well, and I used this structure to get file file size and last modified date. Thanks for your advice!

I dont know why HANDLE was not effective for me!

Regarding comparing wildcards, I have written my own function to compare strings with wildcards :), now my program works like real windows search :)

But I have one more thing to fix, that is the last modified time given by WIN32_FIND_DATA, i FILETIME, and I converted that file time to local system time, which does not include day-light saving time adjustment! Since it a problem in itself!

thanks a lot!

best regards, ricky!

ricky_k6
January 4th, 2006, 12:06 PM
Now I fix the day light time saving problem too.. yeah hooo!!!! my program works like windows search :D

thanks.. this forum is cool!!!

mitz89
January 5th, 2006, 03:39 AM
ei ricky,

can i have a look with your code? because i have quite the same problem. I'm using a .ini file for initializing my values. the problem is that i would like to create a dynamic path or i would like to search for my file.ini whereever it was save under the C: directory.. Thanks in advance.. =)

ricky_k6
January 7th, 2006, 02:44 PM
Sure! I will be glad to help you, PM your e-mail to me, so I will mail you!
Also, u can write here what's the problem , I will try to help u too... but I have no problem to give you the code... :)

NoHero
January 7th, 2006, 03:48 PM
Sure! I will be glad to help you, PM your e-mail to me, so I will mail you!
Also, u can write here what's the problem , I will try to help u too... but I have no problem to give you the code... :)

Rather post the code here to the public so others searching these forums in future can benefit from your achievements.

ricky_k6
January 8th, 2006, 08:08 AM
Rather post the code here to the public so others searching these forums in future can benefit from your achievements.


Sure, I am still testing programs and adding features, for example like searching file names with different locales! Once I finish with whole testing and planned add-onns I will post here. I will be glad to post the code:)