QFileSystemWatcher: определить, был ли файл очищен

У меня есть приложение 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();
}

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

3

Решение

В 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

Другие решения

Этот цикл записи и сброса выполняется довольно быстро (микросекунды !?). Вы не можете ожидать, что 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()
{

}
0

По вопросам рекламы [email protected]