VC++判断目标文件是否被独占(附源码)

       在IM软件中发起文件发送时,如果要发送的是某word文件,并且该word文件被office打开,则会提示文件正在被占用无法发送,如下所示:

VC++判断目标文件是否被独占(附源码)_第1张图片

 那文件被占用到底是如何判断出来的呢?其实很简单,调用系统API函数CreateFile,打开该文件(OPEN_EXISTING),传入FILE_SHARE_READ共享读标记位,如果文件被占用,则文件会打开失败。

1、判断文件被占用的代码

        判断文件被占用的接口函数 IsFileOccupiedByOtherProgram,实现如下:

BOOL IsFileOccupiedByOtherProgram( const CString& strFilePath )
{
	// 检测的办法是通过研究某软件的文件传输表现现象来确定的
	HANDLE hFile = CreateFile( strFilePath, 
		GENERIC_READ,
		FILE_SHARE_READ, // 读共享,但写不共享,如果有程序正在占用着文件写,则该函数会返回失败
		NULL, 
		OPEN_EXISTING, 
		FILE_ATTRIBUTE_NORMAL, 
		NULL );
	if ( hFile != INVALID_HANDLE_VALUE )
	{
		CloseHandle( hFile ); // 文件打开成功,此处必须将句柄关闭,以释放对文件的占用
		return FALSE; // 获取到文件句柄,文件没被占用
	}
	else
	{
		return TRUE; // 没有获取到文件句柄,文件可能被占用
	}
}

2、判断文件夹中是否有被占用的文件

       发起文件传输时,可能是要传一个文件夹,我们要判断文件夹中是否有文件被占用。封装的接口HasFileOccupieddByOtherProgram中一是递归调用本接口,二是调用对单个文件判断的接口IsFileOccupiedByOtherProgram。HasFileOccupieddByOtherProgram接口实现如下:

// 判断文件夹中是否有文件在被其他程序占用(其他程序可能占用着该程序并可能对程序进行写入操作,比如doc文档被WORD打开)
// 如果有被占用的文件,函数即退出
// 参数说明:strFolderDirp[in], bHasFilebOccupied[out], strbOccupiedFilePath[out]
void HasFileOccupieddByOtherProgram( const CString& strFolderDir, BOOL& bHasFilebOccupied, CString& strOccupiedFilePath )
{
	CString  strFindFileName = strFolderDir + _T("\\*.*");
	WIN32_FIND_DATA wfd;
	HANDLE hFindFile = FindFirstFile( strFindFileName, &wfd ); 
	if ( hFindFile == INVALID_HANDLE_VALUE )
	{ 
		return;
	}

	while ( 1 )
	{	
		if ( bHasFileOccupied ) // 有文件被占用,则直接结束循环
		{
			break;
		}

		// 将文件夹中的.和..过滤掉,之前仅判断wfd.cFileName[0]是否为‘.’是有问题的,
		// 比如版本控制的代码的目录下包含掩藏的.svn文件夹,会导致文件夹大小计算有误
		//(偏小)
		if ( _tcscmp( wfd.cFileName, _T(".") ) != 0 && 
			_tcscmp( wfd.cFileName, _T("..") ) != 0 )
		{// 非本级或上级目录	
			CString strFilePath = strFolderDir + _T('\\') + wfd.cFileName;
			if ( wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
			{// 目录
				// 递归
				HasFileOccupieddByOtherProgram( strFilePath, bHasFilebOccupied , strbOccupiedFilePath );
			}
			else
			{// 文件
				BOOL bOccupied = IsFileOccupiedByOtherProgram( strFilePath ); // 检测当前文件是否正被其他程序占用
				if ( bOccupied )
				{
					bHasFileOccupied = true;
					strbOccupiedFilePath = wfd.cFileName;
					break;
				}
			}
		}

		if ( !FindNextFile( hFindFile, &wfd ) )
		{
			break;
		}
	}


	FindClose( hFindFile );
	return;
}

3、再做一次封装,同时支持对文件和文件夹的判断

         调用该接口IsTargetFileOccupied时传入文件或文件夹的路径,然后指明当前判断对象是文件还是文件夹,如下:

// 判断被拖动的文件或文件夹中的文件是否在被其他程序占用(其他程序可能占用着该程序
// 并可能对程序进行写入操作,比如doc文档被WORD打开)
BOOL IsTargetFileOccupied( const CString& strFilePath, const EmFilePathType emFilePathType )
{
	if ( emFilePathType <= emInvalideType || emFilePathType > emFile )
	{
		return FALSE;
	}

	BOOL bFileOccupied = false;
	CString strMsg;
	if ( emFile == emFilePathType ) // 单个文件
	{
		bFileOccupied = IsFileOccupiedByOtherProgram( strFilePath );
		if ( bFileOccupied )
		{
		}
	}
	else // 文件夹
	{
		CString strOccupiedFileName;
		HasFileOccupieddByOtherProgram( strFilePath, bFileOccupied , strOccupiedFileName);
		if ( bFileOccupied )
		{
		}
	}

	return bFileOccupied ;
}

你可能感兴趣的:(VC++常用功能代码封装,文件,文件夹,被独占)