zoukankan      html  css  js  c++  java
  • Qt实战4.简单封装的文件监控

    1 需求描述

    1. 实现一个类能够监控单个目录内文件的变化;
    2. 能够识别文件的创建、改变、删除三种变化。

    2 设计思路

    Qt自带的QFileSystemWatcher提供了一些接口,通过addPath添加一个路径即可对该目录进行监视,当目录发生改变时(比如添加和删除文件)会发出directoryChanged信号,还有个fileChanged信号主要针对单个文件,这里不涉及。
    对于创建了什么文件,删除了什么文件,以及文件名从什么改变成了什么,这些都是无法直接获取到的,如果监视目录后有以下三个信号岂不美哉。

    //文件创建信号
    void fileCreated(const QString &fileName);
    //文件名改变信号
    void fileNameChanged(const QString &previousFileName, const QString &currentFileName);
    //文件删除信号
    void fileRemoved(const QString &fileName);
    

    下面开始造,实现很简单,维护一个文件列表(目录改变前),被监视目录改变后在槽函数中和当前文件列表(目录改变后)进行比对,从而判断文件的变化状态,然后发射对应的信号。

    3 代码实现

    3.1 添加监视目录

    继承QFileSystemWatcher,然后添加一个监视目录,相关代码如下:

    CustomFileWatcher::CustomFileWatcher(QObject *parent) :
        QFileSystemWatcher(parent)
    {
        connect(this, &CustomFileWatcher::directoryChanged, this, &CustomFileWatcher::onDirectoryChanged);
    }
    
    CustomFileWatcher::CustomFileWatcher(const QString &path, QObject *parent) :
        QFileSystemWatcher(QStringList(path), parent)
    {
        QFileSystemWatcher::addPath(path);
    
        QDir dir(path);
        dir.setFilter(QDir::NoDotAndDotDot | QDir::AllEntries);
        m_fileEntryList = dir.entryList();
    
        connect(this, &CustomFileWatcher::directoryChanged, this, &CustomFileWatcher::onDirectoryChanged);
    }
    
    void CustomFileWatcher::addPath(const QString &path)
    {
        if (!directories().isEmpty()) {
            removePath(directories().first());
        }
        QFileSystemWatcher::addPath(path);
    
        QDir dir(path);
        dir.setFilter(QDir::NoDotAndDotDot | QDir::AllEntries);
        m_fileEntryList = dir.entryList();
    }
    

    3.2 判断文件状态

    进入目录改变槽函数,内部通过文件列表(变化前和变化后)的比对,从而判断目录内文件的变化状态,发射对应信号,代码如下:

    void CustomFileWatcher::onDirectoryChanged(const QString &path)
    {
        QDir dir(path);
        dir.setFilter(QDir::NoDotAndDotDot | QDir::AllEntries);
    
        QStringList fileEntryList = dir.entryList();
    
        int previousFileCount = m_fileEntryList.count();
        int currentFileCount = fileEntryList.count();
        if (previousFileCount == currentFileCount) {
            for (int i = 0; i < previousFileCount; i++) {
                QString previousFileName = m_fileEntryList.at(i);
                if (!fileEntryList.contains(previousFileName)) {
                    for (int j = 0; j < currentFileCount; j++) {
                        QString currentFileName = fileEntryList.at(j);
                        if (!m_fileEntryList.contains(currentFileName)) {
                            emit fileNameChanged(previousFileName, currentFileName);
                            m_fileEntryList = fileEntryList;
                            return;
                        }
                    }
                }
            }
        } else if (previousFileCount > currentFileCount) {
            for (int i = 0; i < currentFileCount; i++) {
                m_fileEntryList.removeOne(fileEntryList.at(i));
            }
            emit fileRemoved(m_fileEntryList.first());
            m_fileEntryList = fileEntryList;
        } else {
            QStringList tempList = fileEntryList;
            for (int i = 0; i < previousFileCount; i++) {
                tempList.removeOne(m_fileEntryList.at(i));
            }
            emit fileCreated(tempList.first());
            m_fileEntryList = fileEntryList;
        }
    }
    

    到此,单目录内文件监控功能就算完成了。
    使用的时候只需要添加监视目录再连接相关信号槽即可,目录内文件的变化状态就能获取到了,是不是很简单呢?

    connect(&m_fileWatcher, &CustomFileWatcher::fileNameChanged, this, &MainWindow::onFileNameChanged);
    connect(&m_fileWatcher, &CustomFileWatcher::fileCreated, this, &MainWindow::onFileCreated);
    connect(&m_fileWatcher, &CustomFileWatcher::fileRemoved, this, &MainWindow::onFileRemoved);
    

    4 总结

    根据需求,通过对QFileSystemWatcher简单的封装实现对单个目录内文件变化的监视,外部通过信号槽方式进行后续处理(比如文件的上传、同步等)。其实本例子程序还可以做不少拓展,比如多目录同时监控、目录递归监控等,实现可能会稍稍复杂一点,但是再复杂的功能也是从简单的开始,有个好的开端总是很重要的。

    本例子程序如果对多文件同时删除,可能获取不准确,尽量进行单文件操作。

    5 下载

    完整代码

  • 相关阅读:
    【数论】【快速幂】【扩展欧几里得】【BSGS算法】bzoj2242 [SDOI2011]计算器
    【数论】【ex-BSGS】poj3243 Clever Y
    【数论】【扩展欧几里得】hdu3579 Hello Kiki
    【CCpp程序设计2017】推箱子游戏
    【Miller-Rabin算法】
    【数论】nefu119 组合素数
    【数论】nefu118 n!后面有多少个0
    【树形dp】vijos P1180 选课
    【树形dp】Codeforces Round #405 (rated, Div. 1, based on VK Cup 2017 Round 1) B. Bear and Tree Jumps
    【树形dp】VK Cup 2012 Round 1 D. Distance in Tree
  • 原文地址:https://www.cnblogs.com/luoxiang/p/13474185.html
Copyright © 2011-2022 走看看