Load binary file into buffer in Windows (C++/MFC)



Following is the function to load a binary file into a memory buffer in Windows (C++/MFC).

 
 
//Do not use this for text files as the following code doesn't handle UTF, UNICODE, BOMLESS etc.
BOOL LoadFromBinaryFile(CString strFilePath, BYTE **pBuf, DWORD *pSize)
{
 
	HANDLE hFile = NULL;
	BOOL bRet;
 
	try
	{
		DWORD dwFileSize = 0, dwRead = 0, dwTotalRead = 0;
 
		hFile = CreateFile(strFilePath
		,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING
		,FILE_ATTRIBUTE_NORMAL,NULL);
 
		if (hFile == INVALID_HANDLE_VALUE)
		{
			throw -1;
		}else
		{
			dwFileSize = ::GetFileSize(hFile,NULL);
			if (dwFileSize == 0 )
			{
				*pSize = 0;
				*pBuf = NULL;
			}else
			{
 
				*pBuf = new BYTE[dwFileSize];
				dwRead = 0;
				// the file size.. does not include NULL character
				*pSize = dwFileSize;
 
				do
				{
					dwRead = 0;
					bRet = ReadFile(hFile,(LPVOID)(*pBuf+dwTotalRead)
						,dwFileSize-dwTotalRead,&dwRead,NULL);
 
					dwTotalRead += dwRead;
 
					if (bRet == 0)
					{
						delete *pBuf;
						*pBuf = NULL;
						throw -1;
 
					}
 
				}while( (dwTotalRead != dwFileSize) );
 
			}
 
			CloseHandle(hFile);
 
		}
 
	}catch(int iErr)
	{
		// just assigned to avoid warning of unreferenced local variable
		iErr = -1;
		CloseHandle(hFile);
		return FALSE;
	}
 
	return TRUE;
 
}


Remove duplicates from string array in Windows (C++/MFC/ATL)



Following code removes duplicates from string array in Windows (C++/MFC/ATL).

 
void RemoveDuplicatesFromArray(CAtlArray<CString> &arrValue)
{
	CAtlArray<CString> arrNew;
	INT_PTR i, j, iSize, iNewSize;
	CString strValue;
 
	BOOL bFound = FALSE;
 
	iSize = arrValue.GetCount();
	for(i=0;i<iSize;i++)
	{	
		strValue = arrValue[i];
		strValue.Trim();
		bFound = FALSE;
		iNewSize = arrNew.GetCount(); 
		for(j=0;j<iNewSize;j++)
		{
 
			if (strValue.CompareNoCase(arrNew[j]) == 0)
			{
				bFound = TRUE;
				break;
			}
		}
 
		if (!bFound)
		{
			arrNew.Add(strValue);
		}
	}
 
	//finally copy from new array to the existing array
	arrValue.RemoveAll();
	arrValue.Copy(arrNew);
 
}


Generate a temporary file path with a temp file name in Windows (C++/MFC)



Following function creates a temporary file path with a specific file extension. Optionally, it also creates the temporary file. Coded in C++/MFC (Windows).

 
CString	GenerateTempFilePath(BOOL bCreateDummyFile, CString strFileExtension)
{
 
	TCHAR szFilePath[MAX_PATH];
	CString strTempFolderPath = GetTempFolder();
	AppendBackslash(strTempFolderPath);
 
	if (strFileExtension.Find(_T('.')) == -1)
	{
		strFileExtension = _T(".") + strFileExtension;
	}
 
	//this will also create a file
	GetTempFileName(strTempFolderPath, NULL, 0,szFilePath);
	//delete the temporary file created
	DeleteFile(szFilePath);
 
	if (!strFileExtension.IsEmpty())
	{
		PathRemoveExtension(szFilePath);
		PathAddExtension(szFilePath, strFileExtension);
 
		if (bCreateDummyFile)
		{
			HANDLE hFile = CreateFile(szFilePath, 0, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
			if (hFile)
			{
				CloseHandle(hFile);
			}
		}
	}
 
	return szFilePath;
}


Remove invalid characters from a file name in Windows (C++/MFC)



In Windows, a file or folder name cannot contain the following characters \/:*?\”<>| . Sometimes before saving a file, you may want to remove these invalid characters from the file name. Here is the function written in C++/MFC.

 
void RemoveInvalidFileNameCharacters(CString & strFileName)
{
	LPCTSTR pInvalidCharSet = _T("\\/:*?\"<>|");
	int iLen = (int)_tcslen(pInvalidCharSet);
 
	for(int i=0;i<iLen;i++)
	{
		//remove each invalid character
		strFileName.Remove(pInvalidCharSet[i]);
    }
}


Get path with unique file name in Windows (C++/MFC)



Sometimes, when a file with same name already exists, we wish to generate a new unique file name. The following function does this. Coded in C++/MFC. A number is suffixed to the file name. You can specify your own number format.

 
//generates a file name that is unique so that
//we don't have to replace an existing file in the same path
//so if "New Document.txt" exists
//we will generate "New Document - 1.txt"
//we will keep check if the file exists
//and when the file does not exist we will exit
//strAppendedNumberFormat must contain %d
BOOL GetPathWithUniqueFileName(CString & strFilePath, CString strAppendedNumberFormat)
{
	int iMaxRetries = 1000;
	int iCtr;
	CString strNewFilePath;
	CString strAppendedText;
	CString strExtension;
 
	//if this file does not exist, then just return
	//it means that we can create file with this name
	if (!PathFileExists(strFilePath)) return TRUE;
 
	iCtr = 0;
	while(iCtr < iMaxRetries)
	{
		iCtr++;
		strNewFilePath = strFilePath;
		//will get .txt for example - it includes the period (.)
		strExtension = PathFindExtension(strNewFilePath);
		PathRemoveExtension(strNewFilePath.GetBuffer());
		strNewFilePath.ReleaseBuffer();
		strAppendedText.Format(strAppendedNumberFormat, iCtr);
		strNewFilePath += strAppendedText;
		strNewFilePath += strExtension;
 
		if (!PathFileExists(strFilePath)) break;
 
	}
 
	return TRUE;
}


Delete multiple files using wildcards in Windows (C++/MFC)



Following code uses SHFileOperation Windows API to delete multiple files using wild card (silently without any confirmation box). It deletes only files. Not folders. Coded in C++/MFC.

 
BOOL DeleteFiles(CString strWildCardSourcePath)
{
 
	SHFILEOPSTRUCT sfo;
	TCHAR *pFromBuf = NULL;
 
	int iRet;
 
	//2 because extra NULL character is required 
	//for pFrom and pTo otherwise SHFileOperation will fail
	pFromBuf = new TCHAR[strWildCardSourcePath.GetLength()+2];
	memset(pFromBuf,0,(strWildCardSourcePath.GetLength()+2)*sizeof(TCHAR));
	memcpy(pFromBuf,strWildCardSourcePath,strWildCardSourcePath.GetLength()*sizeof(TCHAR));
 
	USES_CONVERSION;
 
	sfo.hwnd  = NULL;
	sfo.pFrom = CT2CW(LPCTSTR(pFromBuf));
	sfo.pTo = NULL;
	sfo.fFlags = FOF_NOCONFIRMATION|FOF_SILENT|FOF_FILESONLY;
	sfo.wFunc = FO_DELETE;
 
	iRet = SHFileOperation(&sfo);
 
	if (pFromBuf)
	{
		delete pFromBuf;
		pFromBuf = NULL;
	}
 
	return (iRet == 0) ? TRUE : FALSE;
}


Copy or move files using wildcards to another folder in Windows (C++/MFC)



The following function uses SHFileOperation Windows API to copy multiple files using wildcards to another folder. It has option to delete files from source location too (Whether to copy or to move the files. It copies silently without any confirmation message box. It copies only files. Not the folders.

 
BOOL CopyFiles(CString strWildCardSourcePath, CString strTargetPath, BOOL bDeleteFilesFromSourceLocation
								, FILEOP_FLAGS fFlags /*= FOF_NOCONFIRMATION|FOF_SILENT|FOF_FILESONLY*/)
{
 
	SHFILEOPSTRUCT sfo;
	TCHAR *pFromBuf = NULL, *pToBuf = NULL;
 
	int iRet;
 
	//2 for ending NULL characters required by SHFileOperation function's pFrom and pTo
	pFromBuf = new TCHAR[strWildCardSourcePath.GetLength()+2];
	memset(pFromBuf,0,(strWildCardSourcePath.GetLength()+2)*sizeof(TCHAR));
	memcpy(pFromBuf,strWildCardSourcePath,strWildCardSourcePath.GetLength()*sizeof(TCHAR));
 
	//2 for ending NULL characters required by SHFileOperation function's pFrom and pTo
	pToBuf = new TCHAR[strTargetPath.GetLength()+2];
	memset(pToBuf,0,(strTargetPath.GetLength()+2)*sizeof(TCHAR));
	memcpy(pToBuf,strTargetPath,strTargetPath.GetLength()*sizeof(TCHAR));
 
	USES_CONVERSION;
 
	sfo.hwnd  = NULL;
	sfo.pFrom = CT2CW(LPCTSTR(pFromBuf));
	sfo.pTo = CT2CW(LPCTSTR(pToBuf));
	sfo.fFlags = fFlags;
	sfo.wFunc = (bDeleteFilesFromSourceLocation) ? FO_MOVE : FO_COPY ;
 
	iRet = SHFileOperation(&sfo);
 
	if (pFromBuf)
	{
		delete pFromBuf;
		pFromBuf = NULL;
	}
 
	if (pToBuf)
	{
		delete pToBuf;
		pToBuf = NULL;
	}
 
	return (iRet == 0) ? TRUE : FALSE;
 
}


Delete a folder even if not empty in Windows (C++/MFC)



Following is the code to delete a directory folder even if it is not empty in Windows. Coded in C++/MFC.

 
 
BOOL DeleteFolder(CString strFolder, BOOL bDeleteIfNotEmpty )
{	
	BOOL bRet = FALSE;
	int iRet;
 
	/*NOTE: Why are we creating extra buffer?
	because SHFileOperation is expecting
	extra NULL character at the end*/
 
	if (bDeleteIfNotEmpty)
	{
		SHFILEOPSTRUCT sfo;
		TCHAR *pBuf = NULL;
		CString strWildCardsFolder;
		strWildCardsFolder = strFolder;
		AppendBackslash(strWildCardsFolder);
		strWildCardsFolder += _T("*.*");
 
		//2 for ending NULL characters
		pBuf = new TCHAR[strWildCardsFolder.GetLength()+2];
 
		//extra NULL character
		//memset uses void*, bytes, so we will multiple by sizeof(TCHAR)
		memset(pBuf,0,(strWildCardsFolder.GetLength()+2)*sizeof(TCHAR));
		memcpy(pBuf,strWildCardsFolder,strWildCardsFolder.GetLength()*sizeof(TCHAR));
 
 
		ZeroMemory(&sfo, sizeof(SHFILEOPSTRUCT));
		sfo.hwnd  = NULL;
		//to support both ANSI and UNICODE
		//pFrom expects only Wide characters
		sfo.pFrom = pBuf;
		sfo.pTo = NULL;
		sfo.fFlags = FOF_NO_UI;
		sfo.wFunc = FO_DELETE ;
 
		iRet = SHFileOperation(&sfo);
 
		if (pBuf)
		{
			delete pBuf;
			pBuf = NULL;
		}
	}else
	{
		//if directory is not empty
		if (!PathIsDirectoryEmpty(strFolder))
		{
			return FALSE;
		}
	}
 
	// remove the folder at last
	return RemoveDirectory(GetLongFilePathFormat(strFolder));
 
}


Delete oldest file from a folder on Windows in C++/MFC



Following code deletes the oldest file from a folder. We need this when we wish to keep last X copies of a file for backup. So we would just delete the oldest one and create a new backup copy. Coded in C++/MFC.

 
//deletes by creation date
bool DeleteOldestFile(CString folderPath)
{
	if (!PathFileExists(folderPath)) return false;
 
	CFileFind finder;
	CString findString;
	CString filePath;
	WIN32_FILE_ATTRIBUTE_DATA fileAttributes;
	FILETIME oldestFileTime;
	CString oldestFilePath;
 
	ZeroMemory(&fileAttributes, sizeof(WIN32_FILE_ATTRIBUTE_DATA));
 
	//store current time in oldestFileTime so that we can compare in CompareFileTime to get older value
	SYSTEMTIME st;
	GetSystemTime(&st); // gets current time
	SystemTimeToFileTime(&st, &oldestFileTime);
 
 
	folderPath.TrimRight(_T('\\'));
	findString = folderPath + _T("\\*.*");
 
	BOOL bWorking = finder.FindFile(findString);
	while (bWorking)
	{
		bWorking = finder.FindNextFile();
 
		if (finder.IsDots())
			continue;
 
		if (finder.IsDirectory()) continue;
 
		filePath = finder.GetFilePath();
 
		::GetFileAttributesEx(filePath, GetFileExInfoStandard, &fileAttributes);
 
		if (CompareFileTime(&fileAttributes.ftCreationTime, &oldestFileTime) < 0) 
		{
			oldestFileTime = fileAttributes.ftCreationTime;
			oldestFilePath = filePath;
		}
 
	}
 
	finder.Close();
 
	if (oldestFilePath.IsEmpty()) return true;
 
	//delete the file finally
	return (DeleteFile(oldestFilePath) != 0);
 
}


Get total number of files in a folder in Windows (C++/MFC)



Code to get total number of files in a folder in Windows (C++/MFC).

 
int GetTotalFiles(CString folderPath)
{
	if (!PathFileExists(folderPath)) return 0;
 
	CFileFind finder;
	CString findString;
	CString filePath;
	int totalFiles = 0;
 
	folderPath.TrimRight(_T('\\'));
	findString = folderPath + _T("\\*.*");
 
	BOOL bWorking = finder.FindFile(findString);
	while (bWorking)
	{
		bWorking = finder.FindNextFile();
 
		if (finder.IsDots())
			continue;
 
		if (finder.IsDirectory()) continue;
 
		totalFiles++;
	}
 
	finder.Close();
 
	return totalFiles;
}