Get string of temp file and add custom folder - c++

I'm new to C++ and I have been thinking how to get string of the user's temp folder on Windows and append to it a custom folder name.
e.g "\Users\user\AppData\Local\Temp\NameOfCustomFolder"
I've tried this:
std::string szOutput{};
TCHAR path_buf[MAX_PATH];
DWORD ret_val = GetTempPath(MAX_PATH, path_buf);
if (ret_val > MAX_PATH || (ret_val == 0))
{
std::cout << "GetTempPath failed";
}
else
{
szOutput = path_buf, "NameOfCustomFolder\\file.exe"
}
return szOutput;

This does not perform the string concatenation you want
szOutput = path_buf, "NameOfCustomFolder\\file.exe";
Rather do
szOutput = std::string{path_buf} + "NameOfCustomFolder\\file.exe";

If you can use C++17, I would suggest std::filesystem::path::append
It will take care of the path separators, and will make it easy to go cross-platform.

Related

Copy files out of different folders to a specific on in C++

My problem is that i have several folders with the names "MORE0001" "MORE0002" etc and they contain one .SPE-file each.
I want to know if there is a way to extract all the .SPE-files to ONE folder by iterating through all the single-MORE...-folders.
I need sth. like this:
for (int i=0; i<10;i++){
newfile = getfile("directory/MORE%04d/filename.SPE", i);
// copy newfile to a new directory..
}
I hope you guys can help me find an easy solution, because i didn´t find a similar problem yet.
it´s just TOO easy..
i can just use the rename-function..
so it would be like:
rename(path/filename.SPE, newpath/filename.SPE);
thanks, but solved it myself ;)!
I have created one sample program, which might helps to resolve your problem.
#include<Windows.h>
#include<regex>
using namespace std;
void main()
{
regex e1("MORE\\d+");
string szDir = "C:\\*";
WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFileA(szDir.c_str(), &ffd);
do
{
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (regex_match(ffd.cFileName,e1 ))
{
string s1 = ffd.cFileName;
string s2 = "C:\\" + s1 + "\\*";
WIN32_FIND_DATA ffdMORE;
HANDLE hFindMORE = FindFirstFile(s2.c_str(), &ffdMORE);
do
{
regex e2("\\w+.SPE");
if (regex_match(ffdMORE.cFileName,e2))
{
string commondir = "C:\\CommonDir\\";
string sourcePath = "C:\\" + s1 + "\\";
CopyFile(sourcePath.append(ffdMORE.cFileName).c_str(), commondir.append(ffdMORE.cFileName).c_str(), FALSE);
}
} while (FindNextFile(hFindMORE, & ffdMORE) != 0);
}
}
} while (FindNextFile(hFind, &ffd) != 0);
}
Thanks,
Bharathraj

Manually implement c string function with security enhancements

I'm trying to write a replacement for the _tcstok_s function that doesn't skip initial delimiters. (_tcstok_s is a variant of the strtok function that uses TCHARs and includes security enhancements documented at https://msdn.microsoft.com/en-us/library/8ef0s5kh.aspx). I'm doing this due to the annoying behavior of strtok that skips consecutive delimiters. I got the idea from
c++ strtok skips second token or consecutive delimiter.
The thing I don't understand is how to implement the security enhancements that make _tcstok_s better than _tcstok. How to I make sure my re-implementation is as secure as _tcstok_s?
Although my code is C++, I am using C-style strings because I am implementing an MSI DLL.
This is what I have so far, but I don't know how to add the _s security enhancements.
TCHAR *GetNextToken(TCHAR *strToken, const TCHAR *szDelimit, TCHAR **pszContext)
{
if (strToken == NULL)
{
if ((pszContext == NULL) || (*pszContext == NULL))
return NULL;
TCHAR *pToken = _tcspbrk(*pszContext, szDelimit);
TCHAR *szResult = *pszContext;
if (!pToken)
{
*pszContext = NULL;
}
else
{
*pToken++ = _T('\0');
*pszContext = pToken;
}
return szResult;
}
else
{
TCHAR *pToken = _tcspbrk(strToken, szDelimit);
if (!pToken)
{
*pszContext = NULL;
}
else
{
*pToken++ = _T('\0');
*pszContext = pToken;
}
return strToken;
}
}

count the number of directories in a folder C++ windows

I have written a Java program that at one point counts the number of folders in a directory. I would like to translate this program into C++ (I'm trying to learn it). I've been able to translate most of the program, but I haven't been able to find a way to count the subdirectories of a directory. How would I accomplish this?
Thanks in advance
Here is an implementation using the Win32 API.
SubdirCount takes a directory path string argument and it returns a count of its immediate child subdirectories (as an int). Hidden subdirectories are included, but any named "." or ".." are not counted.
FindFirstFile is a TCHAR-taking alias which ends up as either FindFirstFileA or FindFirstFileW. In order to keep strings TCHAR, without assuming availabilty of CString, the example here includes some awkward code just for appending "/*" to the function's argument.
#include <tchar.h>
#include <windows.h>
int SubdirCount(const TCHAR* parent_path) {
// The hideous string manipulation code below
// prepares a TCHAR wildcard string (sub_wild)
// matching any subdirectory immediately under
// parent_path by appending "\*"
size_t len = _tcslen(parent_path);
const size_t alloc_len = len + 3;
TCHAR* sub_wild = new TCHAR[alloc_len];
_tcscpy_s(sub_wild, alloc_len, parent_path);
if(len && sub_wild[len-1] != _T('\\')) { sub_wild[len++] = _T('\\'); }
sub_wild[len++] = _T('*');
sub_wild[len++] = _T('\0');
// File enumeration starts here
WIN32_FIND_DATA fd;
HANDLE hfind;
int count = 0;
if(INVALID_HANDLE_VALUE != (hfind = FindFirstFile(sub_wild, &fd))) {
do {
if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// is_alias_dir is true if directory name is "." or ".."
const bool is_alias_dir = fd.cFileName[0] == _T('.') &&
(!fd.cFileName[1] || (fd.cFileName[1] == _T('.') &&
!fd.cFileName[2]));
count += !is_alias_dir;
}
} while(FindNextFile(hfind, &fd));
FindClose(hfind);
}
delete [] sub_wild;
return count;
}

Save all file names in a directory to a vector

I need to save all ".xml" file names in a directory to a vector. To make a long story short, I cannot use the dirent API. It seems as if C++ does not have any concept of "directories".
Once I have the filenames in a vector, I can iterate through and "fopen" these files.
Is there an easy way to get these filenames at runtime?
Easy way is to use Boost.Filesystem library.
namespace fs = boost::filesystem;
// ...
std::string path_to_xml = CUSTOM_DIR_PATH;
std::vector<string> xml_files;
fs::directory_iterator dir_iter( static_cast<fs::path>(path_to_xml) ), dir_end;
for (; dir_iter != dir_end; ++dir_iter ) {
if ( boost::iends_with( boost::to_lower_copy( dir_iter->filename() ), ".xml" ) )
xml_files.push_back( dir_iter->filename() );
}
I suggest having a look at boost::filesystem if it should be portable and bringing boost in isn't too heavy.
If you don't like boost, try Poco. It has a DirectoryIterator. http://pocoproject.org/
Something like this (Note, Format is a sprintf:ish funciton you can replace)
bool MakeFileList(const wchar_t* pDirectory,vector<wstring> *pFileList)
{
wstring sTemp = Format(L"%s\\*.%s",pDirectory,L"xml");
_wfinddata_t first_file;
long hFile = _wfindfirst(sTemp.c_str(),&first_file);
if(hFile != -1)
{
wstring sFile = first_file.name;
wstring sPath = Format(L"%s%s",pDirectory,sFile.c_str());
pFileList->push_back(sPath);
while(_wfindnext(hFile,&first_file) != -1)
{
wstring sFile = first_file.name;
wstring sPath = Format(L"%s%s",pDirectory,sFile.c_str());
pFileList->push_back(sPath);
}
_findclose(hFile);
}else
return false;
return true;
}

Recursive file search using C++ MFC?

What is the cleanest way to recursively search for files using C++ and MFC?
EDIT: Do any of these solutions offer the ability to use multiple filters through one pass? I guess with CFileFind I could filter on *.* and then write custom code to further filter into different file types. Does anything offer built-in multiple filters (ie. *.exe,*.dll)?
EDIT2: Just realized an obvious assumption that I was making that makes my previous EDIT invalid. If I am trying to do a recursive search with CFileFind, I have to use *.* as my wildcard because otherwise subdirectories won't be matched and no recursion will take place. So filtering on different file-extentions will have to be handled separately regardless.
Using CFileFind.
Take a look at this example from MSDN:
void Recurse(LPCTSTR pstr)
{
CFileFind finder;
// build a string with wildcards
CString strWildcard(pstr);
strWildcard += _T("\\*.*");
// start working for files
BOOL bWorking = finder.FindFile(strWildcard);
while (bWorking)
{
bWorking = finder.FindNextFile();
// skip . and .. files; otherwise, we'd
// recur infinitely!
if (finder.IsDots())
continue;
// if it's a directory, recursively search it
if (finder.IsDirectory())
{
CString str = finder.GetFilePath();
cout << (LPCTSTR) str << endl;
Recurse(str);
}
}
finder.Close();
}
Use Boost's Filesystem implementation!
The recursive example is even on the filesystem homepage:
bool find_file( const path & dir_path, // in this directory,
const std::string & file_name, // search for this name,
path & path_found ) // placing path here if found
{
if ( !exists( dir_path ) ) return false;
directory_iterator end_itr; // default construction yields past-the-end
for ( directory_iterator itr( dir_path );
itr != end_itr;
++itr )
{
if ( is_directory(itr->status()) )
{
if ( find_file( itr->path(), file_name, path_found ) ) return true;
}
else if ( itr->leaf() == file_name ) // see below
{
path_found = itr->path();
return true;
}
}
return false;
}
I know it is not your question, but it is also easy to to without recursion by using a CStringArray
void FindFiles(CString srcFolder)
{
CStringArray dirs;
dirs.Add(srcFolder + "\\*.*");
while(dirs.GetSize() > 0) {
CString dir = dirs.GetAt(0);
dirs.RemoveAt(0);
CFileFind ff;
BOOL good = ff.FindFile(dir);
while(good) {
good = ff.FindNextFile();
if(!ff.IsDots()) {
if(!ff.IsDirectory()) {
//process file
} else {
//new directory (and not . or ..)
dirs.InsertAt(0,nd + "\\*.*");
}
}
}
ff.Close();
}
}
Check out the recls library - stands for recursive ls - which is a recursive search library that works on UNIX and Windows. It's a C library with adaptations to different language, including C++. From memory, you can use it something like the following:
using recls::search_sequence;
CString dir = "C:\\mydir";
CString patterns = "*.doc;abc*.xls";
CStringArray paths;
search_sequence files(dir, patterns, recls::RECURSIVE);
for(search_sequence::const_iterator b = files.begin(); b != files.end(); b++) {
paths.Add((*b).c_str());
}
It'll find all .doc files, and all .xls files beginning with abc in C:\mydir or any of its subdirectories.
I haven't compiled this, but it should be pretty close to the mark.
CString strNextFileName , strSaveLog= "C:\\mydir";
Find.FindFile(strSaveLog);
BOOL l = Find.FindNextFile();
if(!l)
MessageBox("");
strNextFileName = Find.GetFileName();
Its not working. Find.FindNextFile() returning false even the files are present in the same directory``