Windows文件夹管理:删除重建问题

本文介绍了三种删除和重建文件夹的方法:使用Qt的QDir类、Boost库的filesystem库及Windows API。探讨了文件夹被占用无法删除的问题,并提供了解决方案。

  创建工程时,对“临时文件夹删除,然后重建”应该是一个很常用的问题。可是,就是这个常用的删除/递归删除子文件夹,然后重建文件目录的过程,偶尔会出现删不掉的状况。换了两种操作方式,发现都会出这种状况。头疼

    通过try-catch异常捕获还是找到了原因,就是文件夹被打开的情况下是没有办法删除的。在资源管理器中打开,即打开此文件夹,在任务管理器中就会显示有此任务,这应该是一个通用问题,不过之前没有注意到。最后还是师傅亲自出马解决了,remove dir by shell operation在文件夹被打开情况下也暴力删除。

    总结经验:不管认为多么正确,只要有bug就一定是有错误的:最后只能分为解决了错误和解决不了错误两种;一定要再好好看看捕获异常,超有用;师傅就是师傅,经验老道,还是很厉害的。

1. Qt: QDir类递归删除文件

具体操作:从最底层一层一层的向上删除:QDir::rmdirQFile::remove;创建:mkdir

注意事项:QDir::rmdir要求当前dir必须为空,且不能处于被占用状态

头文件:#include <QDir>  #include <QFile>

// 删除文件结构
bool rmdir(const QString &dirPath)
{
	QDir curDir(dirPath);
	if (!curDir.exists())
		return true;

	bool error = false;
	QStringList entries = curDir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden);
	for (QList<QString>::iterator entry = entries.begin(); entry != entries.end(); ++entry)
	{
		QString filePath = QDir::convertSeparators(dirPath + '/' + *entry);
		QFileInfo fileInfo(filePath);
		if (fileInfo.isFile() || fileInfo.isSymLink())
		{
			QFile::setPermissions(filePath, QFile::WriteOwner);
			if (!QFile::remove(filePath))
				error = true;
		}
		else if (fileInfo.isDir())
		{
			if (!removeDir(filePath))
				error = true;
		}
	}

	if (!curDir.rmdir(QDir::convertSeparators(dirPath)))
		error = true;

	return !error;
}
	// 创建文件结构
	// homeDirPath/project
	// homeDirPath/project/work1
	// homeDirPath/project/work2
	// homeDirPath/project/work1/sub_work1
	// homeDirPath/project/work1/sub_work2
	QDir curDir(homeDirPath);
	if (curDir.mkdir(project))
	{
		curDir.cd(project);
		curDir.mkdir(work1);

		curDir.cd(work1);
		curDir.mkdir(sub_work1);
		curDir.mkdir(sub_work2);

		curDir.cdUp();
		curDir.mkdir(work2);
	}

2. Boost: filesystem库实现

具体操作:删除:remove(), remove_all(); 创建:create_directory, create_directories

注意事项:

 QDir::rmdir要求当前dir必须为空,且不能处于被占用状态

 Filesystem库需要system库支持,因此必须先编译system库;filesystem库需要先编译才能使用

头文件:#include <boost/filesystem.hpp>,注意工程配置,添加lib库文件

void filesystem(const char *filePath)
{
	boost::filesystem::path ptest(filePath);
	// remove dir
	try
	{
		if (boost::filesystem::exists(ptest))
		{
			if (boost::filesystem::is_empty(ptest))
				boost::filesystem::remove(ptest);
			else
				boost::filesystem::remove_all(ptest);
		}
	}
	catch (boost::filesystem::filesystem_error& e)
	{
		std::cout << e.path1() << std::endl;
		std::cout << e.what() << std::endl;
	}

	// create path
	try
	{
		boost::filesystem::create_directory(ptest);
		boost::filesystem::create_directories(ptest / work1 / sub_work1);
		boost::filesystem::create_directories(ptest / work1 / sub_work2);
		boost::filesystem::create_directories(ptest / work2);
	}
	catch (boost::filesystem::filesystem_error& e)
	{
		std::cout << e.path1() << std::endl;
		std::cout << e.what() << std::endl;
	}
}

3. Remove Dir by shell operator

具体操作:使用Window API

头文件:#include <windows.h>  #include <shobjidl.h>

#define MAX_PATH 200
// using windows api
bool removeDirByShellOp(const QString &dirPath)
{
	QString dir(dirPath);
	dir.replace('/', '\\');

	// convert the folder path to Unicode string
	char mbcsPath[MAX_PATH];
	strcpy(mbcsPath, dir.toLocal8Bit().constData());
	int requiredSize = MultiByteToWideChar(CP_ACP, 0, mbcsPath, -1, NULL, 0);
	if (requiredSize == 0)
		return false;

	TCHAR *wcsPath = new TCHAR[requiredSize];
	MultiByteToWideChar(CP_ACP, 0, mbcsPath, -1, wcsPath, requiredSize);

	// check if the folder exists
	DWORD attrib = GetFileAttributes(wcsPath);
	if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY))
	{
		IFileOperation *fileOp = NULL;
		IShellItem *shItem = NULL;

		// call shell API to remove the folder
		CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
		HRESULT hr = CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_ALL, IID_IFileOperation, (LPVOID*)&fileOp);
		if (hr == S_OK)
		{
			hr = fileOp->SetOperationFlags(FOF_NOCONFIRMATION | FOFX_NOMINIMIZEBOX);
			if (hr == S_OK)
			{
				SHCreateItemFromParsingName(wcsPath, NULL, IID_PPV_ARGS(&shItem));
				hr = fileOp->DeleteItems(shItem);
				if (hr == S_OK)
					hr = fileOp->PerformOperations();
				shItem->Release();
			}
			fileOp->Release();
		}
		CoUninitialize();

		delete[] wcsPath;
		return (hr == S_OK);
	}

	return true;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值