Qt文件系统源码分析—第二篇QSaveFile

范围

深度

首先指定深度分析深度,否者会陷入代码海洋之中。

本文只分析到Win32 API/Windows Com组件/STL库函数层次,再下层代码不做探究

本文主要了解QSaveFile及其具体实现,使用到父类数据的地方只讨论关键点

QT Private

大部分Qt类有一个类名+Private构成的类,这个类主要用于保存数据、具体实现类功能

比如QObject具有QObjectPrivate来实现具体功能,QFile具有QFilePrivate来实现文件读写

这种数据方式是为了更新时不用动导出的头文件,使程序变更Qt版本时不用做任何修改,直接通过编译

QSaveFile

QSaveFile作用

安全写入文件。保证文件要么全部修改,要么没有修改,不会出现只写一部分情况。

用例

#include <QSaveFile>

#include <QByteArray>

#include <QDebug>

int main(int argc, char* argv[])

{

    QSaveFile file("D:/1.txt");

    if (file.open(QIODevice::WriteOnly))

    {

        file.write("Hello QFile!");

    }

    file.commit();

    return 0;

}

数据变量

QSaveFile本身没有添加的成员变量,所有成员变量全部继承自父类

QSaveFile中具有来自QObject的成员变量d_ptr,其类型为QObjectData指针,d_ptr指向QObjectPrivate,QObjectPrivate继承自QObjectData。

QSaveFile中d_ptr指向的是QSaveFilePrivate

继承关系

QSaveFile>>QFileDevice>>QIODevice>>QObject

QSaveFilePrivate>>QFileDevicePrivate>>QIODevicePrivate>>QObjectPrivate>>QObjectData

数据变量

QSaveFilePrivate单独具有的变量是QString fileName,代表打开文件路径。其他变量都来自父类

QSaveFile细节分层

QSaveFile领域分层

主要功能函数

QSaveFile::QSaveFile

作用

构造QSaveFile,d_ptr指向new QSaveFilePrivate并设置QSaveFilePrivate::fileName为当前文件

QSaveFile::fileName

作用

获取QSaveFile指向名称

实现原理

实际上就是QSaveFilePrivate::fileName

QSaveFile::setFileName 

作用

设置QSaveFile指向名称

实现原理

设置QSaveFilePrivate::fileName为当前文件

QSaveFile::cancelWriting

作用

取消写入文件

调用顺序

QSaveFile::cancelWriting>>QFileDevicePrivate::setError

实现原理

设置写入错误,导致QSaveFile::commit中不替换目标文件

QSaveFile::writeData

作用

将数据写入缓存中。如果超过缓存大小(0x4000),则先将缓存刷新到文件中再数据写入到缓存

实现原理

将数据写入QIODevicePrivate::writeBuffer中

QSaveFile::directWriteFallback

作用

获取QSaveFilePrivate::directWriteFallback的值,默认值为false

实现原理

获取QSaveFilePrivate::directWriteFallback变量

QSaveFile::setDirectWriteFallback

作用

当目标文件目录下无法创建新文件时,设置是否直接写入目标文件。相当于是QFile那种写入,断电时数据只写入一部分。默认值为false

实现原理

设置QSaveFilePrivate::directWriteFallback变量

QSaveFile::open

作用

如果当前目标文件目录能够创建新文件,则创建命名为“目标文件名+随机值”的文件。如果目标文件目录不能创建新文件,并且通过QSaveFile::setDirectWriteFallback设置QSaveFilePrivate::directWriteFallback为true,则直接打开目标文件写入数据。

调用顺序

QSaveFilePrivate::directWriteFallback为默认值false时并且目标文件夹目录可创建新文件。

QSaveFile::Open>>QTemporaryFileEngine::open>>QTemporaryFileName::generateNext>>std::generate>>CreateFile>>QFileDevice::open>>QFileInfo::permissions>>GetFileAttributesEx>>QFileDevice::setPermissions>>QFSFileEngine::setPermissions>>QFileSystemEngine::setPermissions>>_wchmod

实现原理

使用std::generate生成随机字符串加在目标文件名称后,比如目标文件名称D:/1.txt,生成随机字符串eFYrqV,则临时文件名为D:/1.txt.eFYrqV。

再用CreateFile创建D:/1.txt.eFYrqV,如果创建失败分2种情况:

  1. D:/1.txt.eFYrqV已经存在则再生成新的临时文件。
  2. 目标文件目录无创建文件权限则回退校验QSaveFilePrivate::directWriteFallback是否为true,如果为true则直接打开目标文件写入。

创建临时文件成功后利用GetFileAttributesEx读取目标文件权限等属性并用_wchmod赋值给新创建的临时文件

QSaveFile::commit

作用

将目标文件替换为临时文件

调用顺序

QSaveFile::commit>>QFileDevice::close>>QFileDevice::flush>>WriteFile>>fflush>>QFSFileEngine::syncToDisk>>QFSFileEnginePrivate::nativeSyncToDisk>>FlushFileBuffers>>QTemporaryFileEngine::renameOverwrite>>QFSFileEngine::renameOverwrite>>QFileSystemEngine::renameOverwriteFile>>MoveFileEx

实现原理

首先利用WriteFileQIODevicePrivate::writeBuffer写到文件中,并利用fflush刷新缓存到磁盘。

最后利用MoveFileEx将目标文件替换为临时文件

猜你喜欢

转载自blog.csdn.net/sinat_36391009/article/details/130462482