Store Data in memory to access later on - c++

New to C++. I have a code that spins thru directories to look for a specific file (123.txt) and lists the result in a textbox. What i need to do is store these result in memory so i can access it later. An array maybe? I'm not exactly sure how that's done.
Here's the code to execute it:
outfile1.open("pxutil1.log");
DWORD dwSize = MAX_PATH;
char szLogicalDrives[MAX_PATH];
DWORD dwResult = GetLogicalDriveStrings(dwSize, szLogicalDrives);
if (dwResult == 0)
{
// error handling...
}
else if (dwResult > MAX_PATH)
{
// not enough buffer space...
}
else
{
for (char* szSingleDrive = szLogicalDrives; *szSingleDrive != 0; szSingleDrive += (lstrlenA(szSingleDrive) + 1))
{
if (GetDriveTypeA(szSingleDrive) == DRIVE_FIXED)
FindFile(szSingleDrive);
}
}
Here's the code to search for 123.txt and list the restult in a logfile.
std::string dir = directory;
if ((!dir.empty()) && (dir.back() != '\\') && (dir.back() != '/'))
dir += '\\';
WIN32_FIND_DATAA file;
HANDLE search_handle = FindFirstFileA((dir + "*").c_str(), &file);
if (search_handle == INVALID_HANDLE_VALUE)
{
if (GetLastError() != ERROR_FILE_NOT_FOUND)
{
// error handling...
//::MessageBox(NULL, "File not found", "", MB_OK);
}
}
else
{
do
{
if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if ((lstrcmpA(file.cFileName, ".") != 0) && (lstrcmpA(file.cFileName, "..") != 0))
{
//FindFile(dir + file.cFileName);
if (!ExcludeDir(dir + file.cFileName))
{
FindFile(dir + file.cFileName);
}
}
}
else
{
if (lstrcmpA(file.cFileName, "123.txt") == 0)
{
outfile1 << dir.c_str() << endl; //write to log file
}
}
} while (FindNextFileA(search_handle, &file));
if (GetLastError() != ERROR_NO_MORE_FILES)
{
::MessageBox(NULL, "No more files", "", MB_OK);
}
FindClose(search_handle);
}
I thought maybe i could add this to the code, but it doesn't work
string listOfDir[20]
std::string(dir) >> listOfDir;

The standard C++ language does not have overloads of operator>> to input arrays.
The following does not work:
std::cin >> listOfDir;
The C++ language does not have any functions to split a string.
The following does not work:
std::string(dir) >> listOfDir;
The compiler can't find any overload of operator>> that takes a std::string parameter and an array parameter. The statement would be equivalent of:
operator>>(std::string, std::string[]);
In summary, you'll need to write the code yourself to parse or split a string; or you can search the internet for a string library.
If you use std::vector, this code may be more useful:
std::vector<std::string> listOfDir;
//...
listOfDir.push_back(dir);
The above code fragment appends a copy of dir to the vector listOfDir.

Related

using std::regex_search for get all file and folder that be have match with pattern

I want implemented search windows's, I use this :
int main()
{
Search(L"C:\\Users", L"*.txt"); // or Search(L"C:\\Users", L"*.txt");
}
search(path, CString searchString)
{
std::wregex searchPattern = GetPattern(searchString);
result = RecursiveSearch(path, searchPattern);
return result ;
}
RecursiveSearch(path, std::wregex searchPattern)
{
CString newPath = path + CString("\\*");
WIN32_FIND_DATA findData;
HANDLE fileHandle = INVALID_HANDLE_VALUE;
fileHandle = FindFirstFile(newPath, &findData);
do
{
if (INVALID_HANDLE_VALUE != fileHandle)
{
if (std::regex_search(findData.cFileName, searchPattern))
{
if (findData.cFileName != std::wstring(TEXT(".")) && findData.cFileName != std::wstring(TEXT("..")))
{
std::wcout << (const wchar_t*)findData.cFileName
}
}
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (findData.cFileName != std::wstring(TEXT(".")) && findData.cFileName != std::wstring(TEXT("..")))
{
RecursiveSearch(GenerateNewPath(path, ToCString(findData.cFileName)), searchPattern);
}
}
}
else
{
continue;
}
} while (FindNextFile(fileHandle, &findData));
return allObject;
}
this code is ok, it's running successfully. but response is not good.
Some results for this example is :
text.txt
debug-2017-12-18-150616.txt
d.txt.lnk // this isn't not good result
.
.
what is the problem? can you help me detect and fix the bugs?
for pattern add flags :
std::regex_constants::icase | std::regex_constants::ECMAScript | std::regex_constants::optimize;
and add flags to regex_search function :
std::regex_constants::match_continuous
add $ to end of pattern

C++ Getting "Debug Error R6010 -abort() has been called " when i assign promises to threads

i'm getting error:Debug Error R6010 -abort() has been called
in my code :
bool ListFiles(wstring path, wstring mask, vector<wstring>& files) {
HANDLE hFind = INVALID_HANDLE_VALUE;
WIN32_FIND_DATA ffd;
wstring spec;
stack<wstring> directories;
directories.push(path);
files.clear();
while (!directories.empty()) {
path = directories.top();
spec = path + L"\\" + mask;
directories.pop();
hFind = FindFirstFile(spec.c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE) {
return false;
}
do {
if (wcscmp(ffd.cFileName, L".") != 0 && wcscmp(ffd.cFileName, L"..") != 0) {
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
directories.push(path + L"/" + ffd.cFileName);
}
else {
files.push_back(path + L"/" + ffd.cFileName);
}
}
} while (FindNextFile(hFind, &ffd) != 0);
if (GetLastError() != ERROR_NO_MORE_FILES) {
FindClose(hFind);
return false;
}
FindClose(hFind);
hFind = INVALID_HANDLE_VALUE;
}
return true;}
void findText(std::string filename, std::string word , promise<string> &prom) {
std::ifstream f(filename);
std::string s;
std::string notFound = "no";
bool found = false;
if (!f) {
std::cout << "il file non esiste"<<std::endl;
}
while (f.good()) {
std::getline(f, s);
if (s.find(word, 0) != string::npos) {
found = true;
}
}
if (found) {
//cout << "Parola trovata in -> " << filename << endl;
prom.set_value_at_thread_exit(filename);
}
else {
prom.set_value_at_thread_exit(notFound);
}
f.close();}
int main(int argc, char* argv[]){
//vector<std::thread> th;
vector<future<string>> futures;
vector<wstring> files;
string search = "ciao";
string notFound = "no";
if (ListFiles(L"pds", L"*", files)) {
for (vector<wstring>::iterator it = files.begin(); it != files.end(); ++it) {
//wcout << it->c_str() << endl;
wstring ws(it->c_str());
string str(ws.begin(), ws.end());
// Show String
//cout << str << endl;
//Creo una promise per ogni thread in cui andrò a cercare il risulato
std::promise<string> prom;
futures.push_back(prom.get_future());
std::thread(findText,str,search,std::ref(prom)).detach();
}
}
for (int i = 0; i < futures.size(); i++){
futures.at(i).wait();
if (futures.at(i).get().compare(notFound)!=0)
cout << "Parola trovata in ->" <<futures.at(i).get()<<endl;
}
return 0;}
I've tried before without using promises and making each thread printing the name of file if word was found and it worked.
So i don't know why using promises and future to retrive this value cause me this problem...
I'm using VS 2013
Lets take a close look at these lines lines:
for (...) {
...
std::promise<string> prom;
...
std::thread(findText,str,search,std::ref(prom)).detach();
}
First you create a local variable prom, and then you pass a reference to that variable to the thread.
The problem with this is that once the loop iterates, the variable prom goes out of scope and the object is destructed. The reference you once had no longer have anything it references. Using the reference will lead to undefined behavior.
So the solution is to not use references (or pointers to the prom variable), which leads to problems because std::promise can't be copied. It can, however, be moved:
std::thread(findText,str,search,std::move(prom)).detach();
Fir this you might need to make the thread function take the promise argument as a rvalue reference:
void findText(std::string filename, std::string word , promise<string> &&prom) {
...
}
If the above solution doesn't work, then you could use dynamic allocation using the new C++11 smart pointers like std::unique_ptr.
Then the thread function should take the smart pointer by value, like
void findText(std::string filename, std::string word , std::unique_ptr<std::promise<string>> prom) {
...
}
And you create the thread like
auto prom = std::make_unique<std::promise<std::string>>();
// Or if you don't have std::make_unique
// std::unique_ptr<std::promise<std::string>> prom(new std::promise<std::string>);
futures.push_back(prom->get_future();
std::thread(findText,str,search,std::move(prom)).detach();
Remember that in your thread function (findText) the variable prom is a pointer and you need to use the arrow operator when using it, like e.g.
prom->set_value_at_thread_exit(filename);
// ^^
// Note "arrow" operator here

go to other logical drives and continues to search for file

i have a program that search for files of a particular extention(.apk) in a particular logical drive(C:). my system has 3 more partitions :- D: E: F: and these also contains apk files. now i want that my program will also search in these logical drives for the apk's files. how i can do this. please anybody have some suggestion then help me, am trying this since morning. here is my code.....
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> vecAPKFiles;
//std::vector<std::string> vecTxtFiles;
// Search 'c:' for '.apk' files including subdirectories
iRC = SearchDirectory(vecAPKFiles, "c:", "apk");
if(iRC)
{
std::cout << "Error " << iRC << std::endl;
return -1;
}
// Print results
for(std::vector<std::string>::iterator iterAvi = vecAPKFiles.begin();
iterAvi != vecAPKFiles.end();
++iterAvi)
std::cout << *iterAvi << std::endl;
TCHAR szDrive[] = (" A:");
DWORD uDriveMask = GetLogicalDrives();
while(uDriveMask)
{
// Use the bitwise AND, 1â€"available, 0-not available
if(uDriveMask & 1)
printf("%s ", (const char *)szDrive);
// increment, check next drive
++szDrive[1];
// shift the bitmask binary right
uDriveMask >>= 1;
}
printf("\n ");
// Wait for keystroke
_getch();
return 0;
}
You've got a bit weird drive string char szDrive[] = " A:"; (Even with the half-baked TCHAR stuff removed). I'd use char szDrive[] = "A:\"; instead, and increment ++szDrive[0];. You can then pass szDrive to SearchDirectory()

Recursive hard disk search with FindFirstFile & FindNextFile C++

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;
}
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;
}
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);

recursive file search

I'm trying to figure out how to work this thing out .. For some reason, it ends at a certain point.. I'm not very good at recursion and I'm sure the problem lies somewhere there..
Also, even if I checked for cFileName != "..", it still shows up at the end, not sure why but the "." doesn't show up anymore..
void find_files( wstring wrkdir )
{
wstring temp;
temp = wrkdir + L"\\" + L"*";
fHandle = FindFirstFile( temp.c_str(), &file_data );
if( fHandle == INVALID_HANDLE_VALUE )
{
return;
}
else
{
while( FindNextFile( fHandle, &file_data ) )
{
if( file_data.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY &&
wcscmp(file_data.cFileName, L".") != 0 &&
wcscmp(file_data.cFileName, L"..") != 0 )
{
find_files( wrkdir + L"\\" + file_data.cFileName );
}
else if( file_data.dwFileAttributes != FILE_ATTRIBUTE_HIDDEN &&
file_data.dwFileAttributes != FILE_ATTRIBUTE_SYSTEM )
{
results << wrkdir << "\\" << file_data.cFileName << endl;
}
}
}
}
After changing those, the program doesn't enumerate the remaining files left..
For example, if there is a sub folder named test, it enumerates everything inside test but doesn't finish enumerating the files inside the original directory specified.
From the FindFirstFile documentation:
If the function fails or fails to
locate files from the search string in
the lpFileName parameter, the return
value is INVALID_HANDLE_VALUE and the
contents of lpFindFileData are
indeterminate.
You should only exit from the one iteration not the whole program:
if( fHandle == INVALID_HANDLE_VALUE )
{
return;
}
And this may solve your other problem:
else if( file_data.dwFileAttributes != FILE_ATTRIBUTE_HIDDEN &&
file_data.dwFileAttributes != FILE_ATTRIBUTE_SYSTEM &&
wcscmp(file_data.cFileName, L".") != 0 &&
wcscmp(file_data.cFileName, L"..") != 0
)
{
results << wrkdir << "\\" << file_data.cFileName << endl;
}
Also see #fretje's answer as well. It gives another problem that your code has.
Updated new: You need to use fHandle as a local variable as well, not global variable.
Change to:
HANDLE fHandle = FindFirstFile( temp.c_str(), &file_data );
You are changing the value of your local wrkdir variable:
wrkdir = wrkdir + L"\\" + file_data.cFileName;
find_files( wrkdir );
I think you have to call find_files there like this:
find_files( wrkdir + L"\\" + file_data.cFileName );
and not change the value of wrkdir.
There are still several bugs in your code. Try this instead:
void find_files( wstring wrkdir )
{
wstring wrkdirtemp = wrkdir;
if( !wrkdirtemp.empty() && (wrkdirtemp[wrkdirtemp.length()-1] != L'\\') )
{
wrkdirtemp += L"\\";
}
WIN32_FIND_DATA file_data = {0};
HANDLE hFile = FindFirstFile( (wrkdirtemp + L"*").c_str(), &file_data );
if( hFile == INVALID_HANDLE_VALUE )
{
return;
}
do
{
if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
if( (wcscmp(file_data.cFileName, L".") != 0) &&
(wcscmp(file_data.cFileName, L"..") != 0) )
{
find_files( wrkdirtemp + file_data.cFileName );
}
}
else
{
if( (file_data.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) == 0 )
{
results << wrkdirtemp << file_data.cFileName << endl;
}
}
}
while( FindNextFile( hFile, &file_data );
FindClose( hFile );
}
Recursive file search with dirent.h
#include <iostream>
#include <dirent.h>
#include <string.h>
bool isUpDirecory(const char* directory) {
if (strcmp(directory, "..") == 0 || strcmp(directory, ".") == 0)
return true;
else
return false;
}
bool findFile(const std::string& fileName, const std::string& path,
std::string& resultPath) {
dirent* entry;
DIR* dir = opendir(path.c_str());
if (dir == NULL)
return false;
while ((entry = readdir(dir)) != NULL) {
if (entry->d_type == DT_REG) {
if (fileName.compare(entry->d_name) == 0) {
resultPath = path + "/" + entry->d_name;
closedir(dir);
return true;
}
}
}
rewinddir(dir);
while ((entry = readdir(dir)) != NULL) {
if (entry->d_type == DT_DIR) {
if (!isUpDirecory(entry->d_name)) {
std::string nextDirectoryPath = path + "/" + entry->d_name;
bool result = findFile(fileName, nextDirectoryPath, resultPath);
if (result == true) {
closedir(dir);
return true;
}
}
}
}
closedir(dir);
return false;
}
int main() {
std::string path;
bool result = findFile("text.txt", "/home/lamerman/", path);
std::cout << path << std::endl;
return 0;
}
Also, check out the implementation of the CFileFind MFC class.
You still have errors in your code:
you ignore the results of the first search. you call FindFirstFile and handle if it fails. But if it succeeds you do not process already fetched file_data and overwrite it with FindNextFile.
You don't close the search handle. Use FindClose for that.
From your existing code it seems that fHandle is global - it shouldn't. It would break your recursion.
Also I think that you can resolve all the issues in your code by paying more attention to MSDN sample provided in FindFirstFile documentation.