Qt文件操作(二)Qt删除文件、文件夹#慎用QDir::removeRecursively()remove()危险用法

2 篇文章 0 订阅
2 篇文章 0 订阅

又是一次踩坑,程序猿就是这样子成长的吧。

Qt文件操作

用到最多的还是QDir::mkdir 、 QDir::mkpath
不过偶尔也会需要删除QDir::remove , QDir::rmdir , QDir::rmpath
可以看我的上一篇文章
Qt文件操作(一)Qt删除文件、文件夹#QDir类的使用mkdir、mkpath、remove、rmdir、rmpath

记一次踩坑
贴上一段代码的写法(相信不止一个人这样子写)
大致就是酱紫~~!(出于职业操守。改了一下内容再贴上来)
老样子,眼尖的先瞅瞅~
很赞
然后Ctrl+F5跑完,喝口咖啡提提神。正当我准备再次运行exe的时候
在这里插入图片描述
当时我就纳闷了,啥情况?然后看了下目录,我当时表情↓
在这里插入图片描述
在这里插入图片描述
哥敲的一堆代码呢?? 不光dll丢了,而且哥写的其他东西以及
log,产出的文件…blah blah …一堆重要的东西就剩下。。

关键是,回收站是找不到这些丢失文件的!!!

然后锁定了QDir类,一行行找代码,发现了图上的代码

说实话,之前公司都用Qt 4,刚转到Qt 5来不久,我自己也才知道有QDir::removeRecursively()
附上官方解释

bool QDir::removeRecursively()
Removes the directory, including all its contents.
Returns true if successful, otherwise false.
If a file or directory cannot be removed, removeRecursively() keeps going and attempts to delete as many files and sub-directories as possible, then returns false.
If the directory was already removed, the method returns true (expected result already reached).
Note: this function is meant for removing a small application-internal directory (such as a temporary directory), but not user-visible directories. For user-visible operations, it is rather recommended to report errors more precisely to the user, to offer solutions in case of errors, to show progress during the deletion since it could take several minutes, etc.
This function was introduced in Qt 5.0.

再来回顾一下代码

QDir dir;
//中间略去n行实现
//...
//中间略去n行实现
if (QFile::exists(path))
{
	QMessageBox messageBox(QMessageBox::NoIcon,
						   "CSDN", "文件夹已存在是否删除数据 ? ",
						   QMessageBox::Yes | QMessageBox::No, NULL); 

	if (QMessageBox::Yes == messageBox.exec())
	{
		//for debug
		qDebug() << " delete path :" << dir.path();
		return;//这个return 能推导出我的心里阴影面积...
		
		//for debug
		if (!dir.removeRecursively())
		{
			QMessageBox::warning(NULL, "CSDN", "文件正在占用! ");
		}

	}
}

输出结果:
在这里插入图片描述

QDir在无参构造的情况下,dir.path为exe本身的目录,回顾一下官方定义
If a file or directory cannot be removed, removeRecursively() keeps going and attempts to delete as many files and sub-directories as possible
QDir::remove return false肯定意味着删不掉,但是QDir::removeRecursively(),细品一下,Recursively(递归) 也就是说,尽管被占用了文件夹中的部分文件,Qt也会把其余能删的尽可能删掉,然后返回一个false。并且不要指望有什么回滚的方法。所以除了几个加载到的dll,其他全丢了!!

先抛开dir和path不管,就这

if (!dir.removeRecursively())

不得不说这一句写下来,心很大
我很庆幸,是if() 而不是while() //while的话拉去祭天吧
其实也差也不多,只不过如果while(),在某些情况下绝对死循环阻塞Qt的eventloop,顺便提一句Qt尽量避免做太暴力的,不可预知长度的while( xxx )

然而看了一下网上,虽然Qt 5发布了7、8年了,目前的帖子还是在用Qt4的方法比较多,写法也很随意,用了Qt 5的,写法基本上就这样一句带过。实际使用当中删除文件的操作肯定是要非常小心的!

正确的打开方式

	QDir dir(path);	//建议在哪里用到再创建dir,  并且在构造的时候就跟上path
		
	QString temp_path = path;
	QString selfPath = QCoreApplication::applicationDirPath();	//exe的路径

	temp_path.trimmed();	//外部传入的path可能存在多余space干扰

	temp_path.remove("/");
	temp_path.remove("\\");

	selfPath.remove("/");
	selfPath.remove("\\");

	//防止出现需要删除的目录为本身exe目录(或exe父级目录..甚至祖宗级 )
	if ((temp_path == selfPath) || selfPath.contains(temp_path))	
	{
		QMessageBox::warning(NULL, "CSDN", "楼上给的啥路径呀??");
		return;
	}

	if (QFile::exists(path))
	{
		QMessageBox messageBox(QMessageBox::NoIcon,
							   "CSDN", "文件夹已存在是否删除数据 ? ",
							   QMessageBox::Yes | QMessageBox::No, NULL);

		if (QMessageBox::Yes == messageBox.exec())
		{
			qDebug() << " delete path :" << dir.path();
			
			/*判断很多种可能, 此处自行脑补各种可能,毕竟是要删东西!*/
			QFileInfo fi(dir.path());
			if (fi.isRoot())
				return;
			
			
			//this object points to a file or to a symbolic link to a file
			qDebug() << fi.isFile();	
			//this object points to a directory or to a symbolic link to a directory
			qDebug() << fi.isDir();
			//file exists
			qDebug() << fi.exists();
			//this object points to a directory or to a symbolic link to a directory,
			//and that directory is the root directory
			qDebug() << fi.isRoot();


			QString delte_path = getTempDirName(path);	//获取一个临时的存放名
			
			if (!dir.rename(path, delete_path))
			{
				QMessageBox::information(NULL, "CSDN", "文件夹被其他进程占用,无法删除");
			}
			else //能够成功将文件夹重名名,说明未被占用
			{
				bool ret = dir.mkpath(path);
				if (!ret)
					return false;

				dir.setPath(delete_path);
				ret = dir.removeRecursively();
				qDebug() << "remove path [ " << delete_path << " ] " << ret;

			}

			/* 埋了埋了
			if (!dir.removeRecursively())
			{
				QMessageBox::warning(NULL, "CSDN", "文件正在占用! ");
			}
			*/

		}
	}

做程序猿呢,最重要的就是要细心。
你写的接口永远不知道别人会怎么去调用,更别指望别人给的东西都是安全的。就像有的人看到代码贴上就开Run(小声bb)
so 代码中留了path未指定,以及getTempDirName()可以有各种方法去实现。

无独有偶
在这里插入图片描述
原创文章,转载请注明来源

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值