3

特定のファイルで新しいデータがいつ利用可能になるかを知る必要がある QT アプリがあります。そこで、信号を使用して、変更があった場合にメッセージを送信する関数にQFileSystemWatcher接続しました。fileChanged

問題は、fileChanged別のアプリケーションがこのファイルをフラッシュしたときにシグナルが送信されず、ファイルが閉じられた後にのみ送信されることです。

ただし、QFileSystemWatcher のドキュメントには、このシグナルは「指定されたパスにあるファイルが変更、名前変更、またはディスクから削除されたときに」発行されると記載されています。多分私は何かが欠けています。にはどのような変更が含まれてい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();
}

メインウィンドウ.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;
    }
}

これは、ファイルを変更する別のアプリケーションのコードです (これはサードパーティのアプリなので、同期するように変更することはできません)。

#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

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信号は予想通りに発せられました。

于 2016-10-28T08:21:52.177 に答える
0

書き込みとフラッシュのループは非常に高速です (マイクロ秒!?)。QFileSytemWatcher がすべてのアクションの通知を受け取ることは期待できません。タイマーを使用して実装される可能性があるためです..すべてが非常に速く終了するため、何が起こっているのかについて信頼できない情報しか得られません。

私はそれをテストしたところ、この仮定が正しいことがわかりました。次のコードを検討してください。時間指定でも何でも、滞りなく連続で書くライターです。遅延を使用すると、ウォッチャーがすべてのフラッシュについて通知を受ける時間が与えられます。しかし、遅滞なく、2 つ以上のファイル システムの変更が報告されることはめったにありません。

#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 に答える