QFileSystemWatcher:检测文件是否已被刷新

时间:2015-12-14 12:50:27

标签: c++ qt flush qfilesystemwatcher

我有一个QT应用,需要知道特定文件中何时有新数据。所以我使用QFileSystemWatcher并将fileChanged信号连接到一个函数,该函数会在发生更改时发送消息。

问题是,当另一个应用程序刷新此文件时,不会发出fileChanged信号,但只有在它关闭文件后才会发出。

然而,QFileSystemWatcher documentation表示发出此信号"当指定路径上的文件被修改,重命名或从磁盘中移除时#34;。 也许我错过了一些东西; modified中包含哪些更改?如果不包括刷新,如何检测何时将新数据写入文件?

以下是源代码:

的main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

mainwindow.h

#include <QFileSystemWatcher>
#include <QMainWindow>

class MainWindow : public QMainWindow
{
  Q_OBJECT

public:
  explicit MainWindow(QWidget *parent = 0);
  ~MainWindow();

public slots:
  void fileChangedEvent(const QString & path);

private:
  QFileSystemWatcher * watcher;
};

mainwindow.cpp

#include "mainwindow.h"

MainWindow::MainWindow()
{
  watcher = new QFileSystemWatcher();
  connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(fileChangedEvent(QString)));
  watcher->addPath("path to file");
}

void MainWindow::fileChangedEvent(const QString & path)
{
  qDebug() << path;
}

MainWindow::~MainWindow()
{
    if(watcher!=NULL)
    {
        delete watcher;
        watcher=NULL;
    }
}

这是另一个更改文件的应用程序的代码(这是第三方应用程序,因此我无法将其更改为与之同步):

#include <fstream>

int main () {

  std::ofstream outfile ("path to file");

  for (int n=0; n<100; ++n)
  {
    outfile << n;
    outfile.flush();
  }
  outfile.close();

  return 0;
}

仅在调用fileChanged()std::ofstream outfile ("path to file");之后发出outfile.close();信号,而不是在outfile.flush();

之后发出

2 个答案:

答案 0 :(得分:1)

在Windows上,当文件的时间戳发生变化时,似乎发出fileChanged信号,这发生在文件关闭(std::ofstream::close())但不发生时(至少在Windows上)它是刷新的(std::ofstream::flush())。为了测试它,我使用以下函数在每次写入文件时(在调用std::ofstream::flush()之后)显式更新了文件的时间戳:

#include <ctime>
#include <sys/stat.h>
#ifdef _WIN32
#include <sys/utime.h>
#else
#include <utime.h>
#endif

bool UpdateFileTimestamp(std::string fileName) {
    struct stat fstat;
    struct utimbuf new_time;

    if (0 != stat(fileName.c_str(), &fstat))
        return false;

    new_time.actime = fstat.st_atime;
    new_time.modtime = time(NULL);
    if (0 != utime(fileName.c_str(), &new_time))
        return false;

    return true;
}

它有效。 fileChanged信号按预期发出。

答案 1 :(得分:0)

写入和刷新循环非常快(微秒!?)。您不能指望QFileSytemWatcher会注意到所有这些操作,因为它可能是使用计时器实现的......而且一切都过快,以至于您只能不明白地了解正在发生的事情。

我只是测试它并发现这个假设是正确的。请考虑以下代码。它是写作者,可以毫不拖延地连续写入时间或一切。使用延迟将使您的观察者有时间了解每次冲洗。但是没有延迟,它很少报告两个以上的文件系统更改。

#include "mainwindow.h"

#include <QDebug>
#include <QTimer>

MainWindow::MainWindow()
    : m_count(10), m_file("./file")
{

  m_file.open(QFile::Truncate | QFile::ReadWrite);

// CHECK THIS:

  QTimer * t = new QTimer(this);
  connect(t,SIGNAL(timeout()), SLOT(writeChunk()));
  t->start(100);

// AGAINST THIS:

  //for(int i = 0; i < 10; i++) writeChunk();
}

void MainWindow::writeChunk()
{
  qDebug() << "wrinteChunk()";
  m_file.write("Hallo Spencer!");
  m_file.flush();

  if( ! --m_count ) {
      m_file.close();
      qDebug() << "Wrote 10 chunks";
      exit(0);
  }
}

MainWindow::~MainWindow()
{

}