zoukankan      html  css  js  c++  java
  • Qt之QFileSystemWatcher

    QFileSystemWatcher类用于提供监视文件和目录修改的接口。

    QFileSystemWatcher通过监控指定路径的列表,监视文件系统中文件和目录的变更。

    调用addPath()函数可以监控一个特定的文件或目录。如果需要监控多个路径,可以使用addPaths()。通过使用removePath()和removePaths()函数来移除现有路径。

    QFileSystemWatcher检查添加到它的每个路径,已添加到QFileSystemWatcher的文件可以使用的files()函数进行访问,目录则使用directories()函数进行访问。

    当一个文件被修改、重命名或从磁盘上删除时,会发出fileChanged()信号。同样,当一个目录或它的内容被修改或​​删除时,会发射directoryChanged()信号。需要注意:文件一旦被重命名或从硬盘删除,目录一旦从磁盘上删除,QFileSystemWatcher将停止监控。

    注:监控文件和目录进行修改的行为会消耗系统资源。这意味着,你的进程同时监控会有文件数量的限制。一些系统限制打开的文件描述符的数量默认为256。也就是说,如果你的进程试使用addPath()和addPaths()函数添加超过256个文件或目录到文件系统将会失败。

    公共函数

    • bool addPath(const QString & path) 
      如果路径存在,则添加至文件系统监控,如果路径不存在或者已经被监控了,那么不添加。

      如果路径是一个目录,内容被修改或​​删除时,会发射directoryChanged()信号;否则,当文件被修改、重命名或从磁盘上删除时,会发出fileChanged()信号。

      如果监控成功,返回true;否则,返回false.

      监控失败的原因通常依赖于系统,但也包括资源不存在、接入失败、或总的监控数量限制等原因。

    • QStringList addPaths(const QStringList & paths) 
      添加每一个路径至添加至文件系统监控,如果路径不存在或者已经被监控了,那么不添加。

      返回值是不能被监控的路径列表。

    • QStringList directories() const 
      返回一个被监控的目录路径列表。

    • QStringList files() const 
      返回一个被监控的文件路径列表。

    • bool removePath(const QString & path) 
      从文件系统监控中删除指定的路径。如果监控被成功移除,返回true。

      删除失败的原因通常是与系统相关,但可能是由于路径已经被删除。

    • QStringList removePaths(const QStringList & paths) 
      从文件系统监控中删除指定的路径。返回值是一个无法删除成功的路径列表。

    信号

    • void directoryChanged(const QString & path) 
      当目录被修改(例如:在指定的路径中添加或删除一个文件)或从磁盘删除时,这个信号被发射。注意:如果有在短时间内有几种变化,可能有些变化不会发出这个信号。然而,变化的序列中的最后的变化总会发射这个信号。

    注意:这是一个私有信号,可以用于信号连接但不能由用户发出。

    • void fileChanged(const QString & path) 
      当在指定路径中的文件被修改、重命名或从磁盘上删除时,这个信号被发射。

    注意:这是一个私有信号,可以用于信号连接但不能由用户发出。

    示例

    下面,我们来实现一个文件/目录监控的类。

    FileSystemWatcher.h

    #ifndef FILE_SYSTEM_WATCHER_H
    #define FILE_SYSTEM_WATCHER_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 // FILE_SYSTEM_WATCHER_H
    • FileSystemWatcher.cpp
    #include <QDir>
    #include <QFileInfo>
    #include <qDebug>
    #include "FileSystemWatcher.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);
    }

    注释很详细,我就不过多讲解了,下面我们就可以使用了。

    #include "FileSystemWatcher.h"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        FileSystemWatcher::addWatchPath("E:/Test");
    
        ....
        return a.exec();
    }
    • 可以通过FileSystemWatcher::addWatchPath()来监控指定的文件/目录,监控之后,就可以在对应的路径进行更新测试了。
    版权声明:进步始于交流,收获源于分享!纯正开源之美,有趣、好玩、靠谱。。。作者:一去丶二三里 博客地址:http://blog.csdn.net/liang19890820
     
  • 相关阅读:
    netty的ChannelPipeline执行顺序对inBound和outBound执行器造成的影响
    【转载,并做少量修改整合】Java 双亲委派模型与应用:SPI(Service Provider Interface)
    JDK1.8 论ConcurrentHashMap是如何扩容的
    如何解决Vue.js里面noVNC的截图问题之后篇——用web虚拟终端作为替代功能
    hihocoder 1036 Trie图
    Codeforces#390
    Codeforces#386
    codeforces 743D Chloe and pleasant prizes
    codeforces 742E (二分图着色)
    洛谷 P1280 尼克的任务题解
  • 原文地址:https://www.cnblogs.com/senior-engineer/p/8073399.html
Copyright © 2011-2022 走看看