首页 > 编程语言 >C++ Qt开发:QFileSystemWatcher文件监视组件

C++ Qt开发:QFileSystemWatcher文件监视组件

时间:2024-03-08 17:03:16浏览次数:32  
标签:文件 const Qt QFileSystemWatcher C++ QString path 目录

Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QFileSystemWatcher组件实现对文件或目录的监视功能。

QFileSystemWatcher 是 Qt 框架中提供的一个类,用于监视文件系统中的文件和目录的变化。它允许你在文件或目录发生变化时接收通知,并可以用于监视文件的创建、删除、重命名以及内容修改等操作。这对于需要实时监控文件系统变化的应用程序是非常有用的。

下面是关于 QFileSystemWatcher 类的一些常用函数的解释:

函数 描述
QFileSystemWatcher(QObject *parent = nullptr) 构造函数,创建一个文件系统监视器对象。
void addPath(const QString &path) 添加要监视的文件或目录路径。
void addPaths(const QStringList &paths) 添加要监视的多个文件或目录路径。
bool removePath(const QString &path) 移除要监视的文件或目录路径。
void removePaths(const QStringList &paths) 移除要监视的多个文件或目录路径。
bool contains(const QString &path) const 检查监视器是否包含指定的文件或目录路径。
QStringList files() const 返回当前监视的文件路径列表。
QStringList directories() const 返回当前监视的目录路径列表。
void setFilter(QFileSystemWatcher::Filter filter) 设置监视器的过滤器,用于指定要监视的事件类型。
QFileSystemWatcher::Filter filter() const 返回监视器当前的过滤器设置。
void fileChanged(const QString &path) 信号,当监视的文件发生变化时发出。
void directoryChanged(const QString &path) 信号,当监视的目录发生变化时发出。

这些函数允许你动态地添加或移除要监视的文件或目录,设置过滤器以确定要监视的事件类型,并连接相应的信号以处理文件系统的变化事件。

首先我们需要新增一个filesystem.h头文件,该类主要用于实现对文件访问的封装,其中addWatchPath用于增加一个被监控目录,当目录被更新世则调用directoryUpdated,文件被修改调用fileUpdated

#ifndef FILESYSTEM_H
#define FILESYSTEM_H
#include <QObject>
#include <QMap>
#include <QString>
#include <QMap>
#include <QFileSystemWatcher>

class FileSystemWatcher : public QObject
{
    Q_OBJECT

public:
    static void addWatchPath(QString path);

public slots:

    // 目录更新时调用
    void directoryUpdated(const QString &path);

    // 文件被修改时调用
    void fileUpdated(const QString &path);

private:
    explicit FileSystemWatcher(QObject *parent = 0);

private:
    // 单例
    static FileSystemWatcher *m_pInstance;

    // QFileSystemWatcher变量
    QFileSystemWatcher *m_pSystemWatcher;

    // 当前每个监控的内容目录列表
    QMap<QString, QStringList> m_currentContentsMap;
};

#endif // FILESYSTEM_H

接着是filesystem.cpp主函数部分,首先FileSystemWatcher::addWatchPath用于增加一个监控目录。这里的重点在于创建两个信号,当m_pSystemWatcher收到监控数据时,我们让其分别去触发directoryChangedfileChanged两个信号,在信号中分别携带一个参数传递给directoryUpdatedfileUpdated槽函数上进行处理,如果是目录则保存目录中的内容。

void FileSystemWatcher::addWatchPath(QString path)
{
   qDebug() << QString("添加监控目录: %1").arg(path);

    if (m_pInstance == NULL)
    {
        m_pInstance = new FileSystemWatcher();
        m_pInstance->m_pSystemWatcher = new QFileSystemWatcher();

        // 连接QFileSystemWatcher的directoryChanged和fileChanged信号到相应的槽
        connect(m_pInstance->m_pSystemWatcher, SIGNAL(directoryChanged(QString)), m_pInstance, SLOT(directoryUpdated(QString)));
        connect(m_pInstance->m_pSystemWatcher, SIGNAL(fileChanged(QString)), m_pInstance, SLOT(fileUpdated(QString)));
    }

    // 添加监控路径
    m_pInstance->m_pSystemWatcher->addPath(path);

    // 如果添加路径是一个目录,保存当前内容列表
    QFileInfo file(path);
    if (file.isDir())
    {
        const QDir dirw(path);
        m_pInstance->m_currentContentsMap[path] = dirw.entryList(QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Files, QDir::DirsFirst);
    }
}

接着是FileSystemWatcher::directoryUpdated函数的实现部分,如下所示代码,通过QFileSystemWatcher来监听指定目录下文件和子目录的变化。当目录发生变化时,调用directoryUpdated槽函数,比较最新的目录内容和之前保存的内容,找出新增文件、删除文件以及文件重命名等变化。

  • 功能概述
    1. 添加监控路径:通过addWatchPath函数添加监控路径,创建QFileSystemWatcher对象并连接相关信号和槽。
    2. 目录更新处理:当监控的目录发生变化时,调用directoryUpdated槽函数。
    3. 内容变化比较:比较最新的目录内容和之前保存的内容,找出新增文件、删除文件和文件重命名等变化。
    4. 文件重命名处理:如果有文件重命名,输出文件重命名的信息。
    5. 新增文件处理:输出新建文件的信息,并可以在相应的逻辑中处理每个新文件。
    6. 删除文件处理:输出删除文件的信息,并可以在相应的逻辑中处理每个被删除的文件。

代码对文件系统的变化进行了细致的监控和处理,可以用于实时监控目录下文件的变动情况,例如新增文件、删除文件和文件重命名等操作。当用户需要自定义功能时可以在信息输出前对特定目录做进一步处理以达到监视并控制特定文件的功能。

// 任何监控的目录更新(添加、删除、重命名)则调用
void FileSystemWatcher::directoryUpdated(const QString &path)
{
    qDebug() << QString("目录更新: %1").arg(path);

    // 比较最新的内容和保存的内容找出区别(变化)
    QStringList currEntryList = m_currentContentsMap[path];
    const QDir dir(path);

    QStringList newEntryList = dir.entryList(QDir::NoDotAndDotDot  | QDir::AllDirs | QDir::Files, QDir::DirsFirst);

    QSet<QString> newDirSet = QSet<QString>::fromList(newEntryList);
    QSet<QString> currentDirSet = QSet<QString>::fromList(currEntryList);

    // 添加了文件
    QSet<QString> newFiles = newDirSet - currentDirSet;
    QStringList newFile = newFiles.toList();

    // 文件已被移除
    QSet<QString> deletedFiles = currentDirSet - newDirSet;
    QStringList deleteFile = deletedFiles.toList();

    // 更新当前设置
    m_currentContentsMap[path] = newEntryList;

    if (!newFile.isEmpty() && !deleteFile.isEmpty())
    {
        // 文件/目录重命名
        if ((newFile.count() == 1) && (deleteFile.count() == 1))
        {
           qDebug() << QString("文件重命名 %1 到 %2").arg(deleteFile.first()).arg(newFile.first());
        }
    }
    else
    {
        // 添加新文件/目录至Dir
        if (!newFile.isEmpty())
        {
           qDebug() << "新建文件或目录: " << newFile;

            foreach (QString file, newFile)
            {
                // 处理操作每个新文件....
            }
        }

        // 从Dir中删除文件/目录
        if (!deleteFile.isEmpty())
        {
            qDebug() << "删除文件或目录: " << deleteFile;

            foreach(QString file, deleteFile)
            {
                // 处理操作每个被删除的文件....
            }
        }
    }
}

同理,当文件被修改时则调用fileUpdated函数,只需要去除绝对路径与文件名即可,如下代码所示;

void FileSystemWatcher::fileUpdated(const QString &path)
{
    QFileInfo file(path);
    QString strPath = file.absolutePath();
    QString strName = file.fileName();

   qDebug() << QString("文件 %1 路径 %2 修改").arg(strName).arg(strPath);
}

你可以自行运行课件FileSystemWatcher.zip来观察监控效果,如下图;

标签:文件,const,Qt,QFileSystemWatcher,C++,QString,path,目录
From: https://www.cnblogs.com/LyShark/p/18061383

相关文章

  • C/C++结构体最详细的讲解
    转载自知乎:https://zhuanlan.zhihu.com/p/6117720311.定义结构体法一(推荐,写法简单)structStudent{stringm_Name;intm_Age;Student()=default;Student(stringname,intage):m_Name(name),age(m_Age){}};一般定义结构体和类时,如果不写关于构造函数的任何东西,结构......
  • 植物大战僵尸,用QT注入代码,AT&T汇编语法
    遇到了硬茬子,找了半天资料才找到,因为这个QT是mingw编译的,好像编译器是gcc吧,我也不太懂,但是查了半天知道他的语法是AT&T,而我在学汇编的时候学的是8086,好像叫intel语法。所以开头就碰壁到崩溃。。但是又不想放弃换MFC框架。。也不想用QT5.0+的版本。因为毕竟以后还是高版本好用吗。......
  • c++多线程
    1.线程库的使用创建进程#include<iostream>#include<thread>//线程库头文件usingnamespacestd;voidthread_1(){cout<<"子线程1"<<endl;}intthread_2(intx){cout<<"子线程2"<<endl;returnx;}intm......
  • Qt中关于setGeometry()函数的问题
    setGeometry是相对于父窗体来说的一种对子窗体进行位置设置的方法。当我用在不同的窗体的时候发现有不同的形式QMainWindow和QWidget都是相对父窗体来说的,可是QDialog用上这个设置位置的函数,却是相对于桌面而言的。但是按照道理,他们都是继承的QWidget,setGeometry这个函数的功能......
  • C++中的static关键字
    在C++中,static是一个关键字,用于声明静态变量、静态函数、静态类成员以及静态局部变量。static关键字的作用取决于它所修饰的上下文,以下是static关键字的几种常见用法:静态变量:在函数内部使用static关键字声明的变量称为静态局部变量。静态局部变量的生命周期延长到整个程......
  • C++中OpenCV、Armadillo矩阵数据格式的转换方式
      本文介绍在C++语言中,矩阵库Armadillo的mat、vec格式数据与计算机视觉库OpenCV的Mat格式数据相互转换的方法。  在C++语言的矩阵库Armadillo与计算机视觉库OpenCV中,都有矩阵格式的数据类型;而这两个库在运行能力方面各有千秋,因此实际应用过程中,难免会遇到需要将二者的矩阵格......
  • C++中的volatile关键字
    在C++中,volatile是一个关键字,用于告诉编译器,该变量的值可能会在未知的时刻被意外地改变,因此编译器对于该修饰的变量的操作时应该保持对该变量内存地址的直接内存访问操作,而不应对访问该变量的代码进行任何优化。。volatile关键字的主要作用是告诉编译器不要对该变量进行优化,......
  • C++ Qt开发:QFileSystemModel文件管理组件
    Qt是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QFileSystemModel组件实现文件管理器功能。QFileSystemModel是Qt框架中的一个关键类,用于......
  • 复试C++ 异常 看程序写结果
    就算每一个case后面都没有break,throw相当于起了break的作用?#include<iostream>#include<stdexcept>usingnamespacestd;classErrorA:publicruntime_error{public:ErrorA():runtime_error{"errorAAAA"}{}};classErrorB:publicruntime_erro......
  • Qt开发,报错:Error while building/deploying project untitled (kit: ....)
    1、问题描述 Qt开发,编译时,报错如下:1Cannotfindfile:F:\linux\...\Console.pro.213:49:47:进程"D:\Qt\Qt5.14.2\5.14.2\msvc2017_64\bin\qmake.exe"退出,退出代码2。3Errorwhilebuilding/deployingprojectConsole(kit:DesktopQt5.14.2MSVC201764bit)4......