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


    范围

    深度

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

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

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

    QT Private

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

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

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

    QSaveFile

    QSaveFile作用

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

    用例

    #include 

    #include 

    #include 

    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将目标文件替换为临时文件

  • 相关阅读:
    阿里巴巴面试题- - -JVM篇(二十一)
    差分放大器的精髓:放大差模信号 抑制共模信号
    [Mysql] 删除数据
    新型移动互联技术要点
    少即是多:视觉SLAM的点稀疏化(IROS 2022)
    删除的通话记录也能找回!如何iPhone很早以前的通话记录
    Find My行李箱|苹果Find My技术与行李箱结合,智能防丢,全球定位
    微信小程序 vue+uniapp书架小说阅读推荐系统
    SpringBoot 实体参数(用于请求参数比较多时使用)
    Sentinel配置持久化到Nacos实现流控熔断
  • 原文地址:https://blog.csdn.net/sinat_36391009/article/details/130462482