3

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

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

但是,QFileSystemWatcher 文档说这个信号是“当指定路径的文件被修改、重命名或从磁盘中删除时”发出的。也许我错过了一些东西;包含哪些变化modified?如果不包括刷新,如何检测新数据何时写入文件?

这是源代码:

主文件

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

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

    return a.exec();
}

主窗口.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;
};

主窗口.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;
    }
}

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

#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();

4

2 回答 2

1

fileChanged在 Windows 上,当文件的时间戳发生变化时,似乎会发出信号,这发生在文件关闭时( 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信号按预期发出。

于 2016-10-28T08:21:52.177 回答
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()
{

}
于 2015-12-14T13:16:21.947 回答