项目场景:
在文件打开的时候,使用QFile的QIODevice的不同模式,会出现不同的表现(这是我一个同事当时遇到的问题,现在拿来分析分析,以下的所有事例代码均用于示范使用,有些内容因为不是特别重要就给抹去了,因此显得可能有些不规范,如果读者想要自己去实现的话,需要将其添加完整)。
问题描述:
QFile的文件打开常用的几种方式包括只读、只写、读写等。当时我那个同事在使用QIODevice::ReadWrite或者是QIODevice::WriteOnly模式时,会出现文件打开失败的情况。
当时我挺好奇的 ,于是就特意写了下面的代码用于测试:
#include <QFile>
#include <QDebug>
int main(int argc, char *argv[])
{
QFile file("xxx.xml");
qDebug() << file.open(QIODevice::ReadWrite);
file.close();
return 0;
}
用上述代码,同时启动两份,在APP1中调试信息为“true”,而在APP2中调试信息为“false”。
但是如果将APP2中文件的打开方式变为file.open(QIODevice::ReadOnly),在启动APP1之后,再次启动APP2,此时两者的的调试信息均为“true”。
另外,还有一点值得一提,就是QFile类型的变量file本身有一个函数是isOpen,用于判断其是否处于打开方式,鉴于此,此时将上述代码稍作修改,加入file的isOpen判断函数,代码如下:
#include <QFile>
#include <QDebug>
int main(int argc, char *argv[])
{
QFile file("xxx.xml");
qDebug() << file.isOpen();
qDebug() << file.open(QIODevice::ReadWrite);
file.close();
return 0;
}
此时,在APP1以及APP2的调试信息中,均会输出“false”的调试信息。
APP1中输出“false”很容易理解,但是APP2中同样也是输出“false”的结果,貌似跟file.open的调试信息冲突,毕竟,如果isOpen的调试信息如果为假的话,想当然地就会认为该文件资源没有被占用,也就是说open应该输出“true”,但是事实并非如此,原因在下面进行分析。
原因分析:
从上面的的问题分析中可以得出,在一个文件被以包含“写”的方式打开之后,后台(应该是内核进行处理)会对改文件施加一个锁(具体的锁的内容在后面补充),此时如果有另外一个进程想要以包含写的方式去访问该文件,会出现权限冲突导致的文件打开失败的情况。
实际上这是系统对于文件资源的一种安全保护机制,毕竟程序员最不可饶恕的错误就是数据丢失。
关于上面的第二点isOpen的打印输出貌似有问题的情况,要想搞清楚这个问题,需要知道isOpen这玩意代表的是谁?
可能会很惊讶,第一印象一般都会想当然地认为这玩意不就是代表需要处理的文件资源吗?其实不然,isOpen代表的是QFile类型的file变量(这里定义的file这玩意实际上是一个device,不要被名字欺骗了),关于此函数,帮助手册中给予的解释是:
Returns true if the device is open; otherwise returns false.
A device is open if it can be read from and/or written to.
注意,这里面用的是device,而不是file,device代表的是具体的设备,而不是文件。
因此,file这个变量本身相当于是设备的代言人,在file执行绑定文件行为之后,设备就可以完成对于文件的相关操作。
此时的file仍旧是表示的device,从不严谨的角度来看,可以将file这个变量理解为对应文件的一个句柄,可以通过这个句柄执行对于文件的操作,但是这个句柄并不等同于文件本身。
在调用file的isOpen函数的时候,判断的实际上不是文件是否被打开,而是file这个设备本身有没有被打开。此时APP1和APP2中的file都是出于刚刚创建的时候,没有被打开,因此调试信息均为“false”,这点事毋庸置疑的。
但是因为这个函数判定的是device而不是file,因此无法通过该函数实现对于文件是否被打开的判定操作(如果实在是想要判定文件的话,其实可以使用Windows本身的一些底层函数来判定,这里就不细说了),这里往往是像我这样的初学者一般考虑不到的地方。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)