C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C++ Qt监控文件状态变化

C/C++ Qt监控文件状态变化方式

作者:王瑞MVP

本文介绍了Qt框架中的QFileSystemWatcher类,讲解其用于跨平台监控文件和目录变化的功能及用法,包含信号槽机制实现自动通知,示例展示了如何监控指定目录并响应文件变动

C++ Qt监控文件状态变化

QFileSystemWatcher 是 Qt 框架中的一个类,用于监视文件和目录的变化。

它提供了一种机制,可以在文件系统中的特定文件或目录发生变化时通知应用程序。

以下是 QFileSystemWatcher 的主要特性和用法:

在示例中,QFileSystemWatcher 被用于监视文件和目录的变化。

当文件内容被修改或目录中的文件被删除时,相应的信号槽会被触发,从而执行相应的操作。

定义头文件 filesystem.h

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

class FileSystemWatcher : public QObject
{
    Q_OBJECT

public:
    static void addWatchPath(QString path);

public slots:
    void directoryUpdated(const QString &path);  // 目录更新时调用,path是监控的路径
    void fileUpdated(const QString &path);   // 文件被修改时调用,path是监控的路径

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

private:
    static FileSystemWatcher *m_pInstance; // 单例
    QFileSystemWatcher *m_pSystemWatcher;  // QFileSystemWatcher变量
    QMap<QString, QStringList> m_currentContentsMap; // 当前每个监控的内容目录列表

};
#endif // FILESYSTEM_H

实现头文件 filesystem.cpp

#include <QDir>
#include <QFileInfo>
#include <qDebug>
#include "filesystem.h"

FileSystemWatcher* FileSystemWatcher::m_pInstance = NULL;
FileSystemWatcher::FileSystemWatcher(QObject *parent)
    : QObject(parent)
{

}

// 监控文件或目录
void FileSystemWatcher::addWatchPath(QString path)
{
    qDebug() << QString("Add to watch: %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);
    }
}

// 只要任何监控的目录更新(添加、删除、重命名),就会调用。
void FileSystemWatcher::directoryUpdated(const QString &path)
{
    qDebug() << QString("Directory updated: %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("File Renamed from %1 to %2").arg(deleteFile.first()).arg(newFile.first());
        }
    }
    else
    {
        // 添加新文件/目录至Dir
        if (!newFile.isEmpty())
        {
            qDebug() << "New Files/Dirs added: " << newFile;

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

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

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

// 文件修改时调用
void FileSystemWatcher::fileUpdated(const QString &path)
{
    QFileInfo file(path);
    QString strPath = file.absolutePath();
    QString strName = file.fileName();

    qDebug() << QString("The file %1 at path %2 is updated").arg(strName).arg(strPath);
}

主程序main.cpp代码中

直接调用

FileSystemWatcher::addWatchPath("c://test");

监控C盘下的test目录,当有文件发生变化时自动触发。

#include <QCoreApplication>
#include "filesystem.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    FileSystemWatcher::addWatchPath("c://test");

    return a.exec();
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文