filemisc.cpp

来自「管理项目进度工具的原代码」· C++ 代码 · 共 777 行 · 第 1/2 页

CPP
777
字号
#include "stdafx.h"
#include "filemisc.h"
#include "misc.h"

#include <sys/utime.h>
#include <sys/stat.h>
#include <direct.h>

///////////////////////////////////////////////////////////////////////////////////////////////////

CFileBackup::CFileBackup(const CString& sFile, const CString& sExt)
{
	MakeBackup(sFile, sExt);
}

CFileBackup::~CFileBackup()
{
	if (FileMisc::FileExists(m_sBackup))
		::DeleteFile(m_sBackup);
}

BOOL CFileBackup::MakeBackup(const CString& sFile, const CString& sExt)
{
	ASSERT (m_sFile.IsEmpty() && m_sBackup.IsEmpty());

	if (!m_sFile.IsEmpty() || !m_sBackup.IsEmpty())
		return FALSE;

	if (!FileMisc::FileExists(sFile))
		return FALSE;

	m_sFile = sFile;
	m_sBackup = BuildBackupPath(sFile, sExt);

	return ::CopyFile(m_sFile, m_sBackup, FALSE);
}

BOOL CFileBackup::RestoreBackup()
{
	ASSERT (!m_sFile.IsEmpty() && !m_sBackup.IsEmpty());

	if (m_sFile.IsEmpty() || m_sBackup.IsEmpty())
		return FALSE;

	return ::CopyFile(m_sBackup, m_sFile, FALSE);
}

CString CFileBackup::BuildBackupPath(const CString& sFile, const CString& sExt)
{
	CString sBackup(sFile);

	sBackup.TrimRight();

	// add extension
	if (sExt.IsEmpty())
		sBackup += ".bak";
	else
	{
		if (sExt.Find('.') == -1)
			sBackup += '.';

		sBackup += sExt;
	}

	return sBackup;
}

///////////////////////////////////////////////////////////////////////////////////////////////////

void FileMisc::TerminatePath(CString& sPath)
{
	sPath.TrimRight();

	if (sPath.ReverseFind('\\') != (sPath.GetLength() - 1))
		sPath += '\\';
}

void FileMisc::UnterminatePath(CString& sPath)
{
	sPath.TrimRight();

	int len = sPath.GetLength();

	if (sPath.ReverseFind('\\') == (len - 1))
		sPath = sPath.Left(len - 1);
}

void FileMisc::ReplaceExtension(CString& sFilePath, const char* szExt)
{
	CString sDrive, sDir, sFile;

	SplitPath(sFilePath, &sDrive, &sDir, &sFile);
	MakePath(sFilePath, sDrive, sDir, sFile, szExt);
}

CString& FileMisc::ValidateFilepath(CString& sFilepath)
{
	sFilepath.TrimLeft();
	sFilepath.TrimRight();

	sFilepath.Replace("/", "");
	sFilepath.Replace("*", "");
	sFilepath.Replace("?", "");
	sFilepath.Replace("\"", "");
	sFilepath.Replace("<", "");
	sFilepath.Replace(">", "");
	sFilepath.Replace("|", "");

	// make sure if a colon exists it is the 2nd pos
	int nColon = sFilepath.Find(':');

	while (nColon != -1 && nColon != 1)
	{
		// delete the colon
		sFilepath = sFilepath.Left(nColon) + sFilepath.Mid(nColon + 1);
		nColon = sFilepath.Find(':', nColon);
	}

	return sFilepath;
}

CString& FileMisc::ValidateFilename(CString& sFilename)
{
	sFilename.Replace("\\", "");
	sFilename.Replace(":", "");
	
	return ValidateFilepath(sFilename);
}

const char* FileMisc::GetFileNameFromPath(const char* szFilepath)
{
	const char* szFilename = strrchr(szFilepath, '\\');

	if (szFilename)
		return szFilename + 1;

	// else
	return szFilepath;
}

time_t FileMisc::GetLastModified(const char* szPath)
{
	struct _stat st;

	if (!szPath || _stat(szPath, &st) != 0)
		return 0;

	// files only
	if ((st.st_mode & _S_IFDIR) == _S_IFDIR)
		return 0;

	return st.st_mtime;
}

bool FileMisc::GetLastModified(const char* szPath, SYSTEMTIME& sysTime, bool bLocalTime)
{
	ZeroMemory(&sysTime, sizeof(SYSTEMTIME));

	DWORD dwAttr = ::GetFileAttributes(szPath);

	// files only
	if (dwAttr == 0xFFFFFFFF)
		return false;

	WIN32_FIND_DATA findFileData;
	HANDLE hFind = FindFirstFile((LPTSTR)szPath, &findFileData);

	if (hFind == INVALID_HANDLE_VALUE)
		return FALSE;

	FindClose(hFind);

	FILETIME ft = findFileData.ftLastWriteTime;

	if (bLocalTime)
		FileTimeToLocalFileTime(&findFileData.ftLastWriteTime, &ft);

	FileTimeToSystemTime(&ft, &sysTime);
	return true;
}

bool FileMisc::ResetLastModified(const char* szPath)
{
	::SetFileAttributes(szPath, FILE_ATTRIBUTE_NORMAL);

	return (_utime(szPath, NULL) == 0);
}

bool FileMisc::DeleteFolderContents(const char* szFolder, BOOL bIncludeSubFolders, const char* szFileMask, HANDLE hTerminate, BOOL bProcessMsgLoop)
{
	// if the dir does not exists just return
	if (!FolderExists(szFolder))
		return true;

	// if a file mask has been specified with subfolders we need to do 2 passes on each folder, 
	// one for the files and one for the sub folders
	int nPasses = (bIncludeSubFolders && (szFileMask && lstrlen(szFileMask))) ? 2 : 1;
		
	bool bResult = true;
	bool bStopped = (WaitForSingleObject(hTerminate, 0) == WAIT_OBJECT_0);

	for (int nPass = 0; !bStopped && nPass < nPasses; nPass++)
	{
		CString sSearchSpec(szFolder), sMask(szFileMask);

		if (sMask.IsEmpty() || nPass == 1) // (nPass == 1) == 2nd pass (for folders)
			sMask = "*.*";

		TerminatePath(sSearchSpec);
		sSearchSpec += sMask;

		WIN32_FIND_DATA finfo;
		HANDLE hSearch = NULL;

		if ((hSearch = FindFirstFile(sSearchSpec, &finfo)) != INVALID_HANDLE_VALUE) 
		{
			do 
			{
				if (bProcessMsgLoop)
					Misc::ProcessMsgLoop();

				if (finfo.cFileName[0] != '.') 
				{
					CString sItem(szFolder);
					sItem += "\\";
					sItem += finfo.cFileName;

					if (finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
					{
						if (bIncludeSubFolders && (nPass == 1 || nPasses == 1))
						{
							if (DeleteFolderContents(sItem, TRUE, szFileMask, hTerminate, bProcessMsgLoop))
							{
								if (!szFileMask || !lstrlen(szFileMask))
									bResult = (RemoveDirectory(sItem) == TRUE);
							}
						}
					}
					else 
						bResult = (DeleteFile(sItem) == TRUE);
				}

				bStopped = (WaitForSingleObject(hTerminate, 0) == WAIT_OBJECT_0);
			} 
			while (!bStopped && bResult && FindNextFile(hSearch, &finfo));
			
			FindClose(hSearch);
		}
	}

	return (!bStopped && bResult);
}

bool FileMisc::RemoveFolder(const char* szFolder, HANDLE hTerminate, BOOL bProcessMsgLoop)
{
	// if the dir does not exists just return
	if (!FolderExists(szFolder))
		return true;

	if (DeleteFolderContents(szFolder, TRUE, NULL, hTerminate, bProcessMsgLoop))
	{
		::SetFileAttributes(szFolder, FILE_ATTRIBUTE_NORMAL);
		return (RemoveDirectory(szFolder) == TRUE);
	}

	return false;
}

double FileMisc::GetFolderSize(const char* szFolder, BOOL bIncludeSubFolders, const char* szFileMask, HANDLE hTerminate, BOOL bProcessMsgLoop)
{
	// if the dir does not exists just return
	if (!FolderExists(szFolder))
		return 0;
	
	double dSize = 0;

	WIN32_FIND_DATA finfo;
	CString sSearchSpec(szFolder), sFileMask(szFileMask);

	if (sFileMask.IsEmpty())
		sFileMask = "*.*";

	TerminatePath(sSearchSpec);
	sSearchSpec += sFileMask;

	BOOL bStopped = (WaitForSingleObject(hTerminate, 0) == WAIT_OBJECT_0);
	HANDLE h = NULL;
		
	if (!bStopped && (h = FindFirstFile(sSearchSpec, &finfo)) != INVALID_HANDLE_VALUE) 
	{
		do 
		{
			if (bProcessMsgLoop)
				Misc::ProcessMsgLoop();

			if (finfo.cFileName[0] != '.') 
			{
				if (finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
				{
					if (bIncludeSubFolders)
					{
						CString sSubFolder(szFolder);
						sSubFolder += "\\";
						sSubFolder += finfo.cFileName;
						
						dSize += GetFolderSize(sSubFolder, TRUE, sFileMask, hTerminate, bProcessMsgLoop);
					}
				}
				else 
					dSize += (finfo.nFileSizeHigh * ((double)MAXDWORD + 1)) + finfo.nFileSizeLow;
			}

			bStopped = (WaitForSingleObject(hTerminate, 0) == WAIT_OBJECT_0);
		}
		while (!bStopped && FindNextFile(h, &finfo));
		
		FindClose(h);
	} 

	return bStopped ? -1 : dSize;
}

bool FileMisc::FolderExists(const char* szFolder)
{
	DWORD dwAttrib = GetFileAttributes(szFolder);

	return (dwAttrib != 0xffffffff && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}

bool FileMisc::FileExists(const char* szFile)
{
	DWORD dwAttrib = GetFileAttributes(szFile);

	return (dwAttrib != 0xffffffff && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY) == 0);
}

bool FileMisc::FolderFromFilePathExists(const char* szFilePath)
{
	return FolderExists(GetFolderFromFilePath(szFilePath));
}

CString FileMisc::GetCwd()
{
	char szCwd[MAX_PATH];
	GetCurrentDirectory(MAX_PATH, szCwd);

	return szCwd;
}

CString FileMisc::GetFolderFromFilePath(const char* szFilePath)
{
	CString sFolder;

	// check if its a folder already
	if (FolderExists(szFilePath))
	{
		sFolder = szFilePath;
	}
	else
	{
		// remove file ending
		CString sDrive, sDir;

		SplitPath(szFilePath, &sDrive, &sDir);
		MakePath(sFolder, sDrive, sDir);
	}

	return sFolder;
}

bool FileMisc::CreateFolderFromFilePath(const char* szFilePath)
{
	return CreateFolder(GetFolderFromFilePath(szFilePath));
}

bool FileMisc::PathHasWildcard(const char* szFilePath)
{
	return (strchr(szFilePath, '?') || strchr(szFilePath, '*'));
}

bool FileMisc::CreateFolder(const char* szFolder)
{
	if (FolderExists(szFolder))
		return true;

	// start from the highest level folder working to the lowest
	CString sFolder, sRemaining(szFolder);
	UnterminatePath(sRemaining);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?