从一个内容不断变化的文件夹中删除文件

4
我有一个主线程和一个处理文件的线程。当主线程监控的文件夹发生变化时,将发送信号给处理线程开始工作。在处理完文件后,我希望将其删除,然后让文件夹检查是否还有更多文件。如果有,则重复该过程。
我的问题在于在处理线程中重复检查文件夹。下面的代码列出了该函数,问题在于我无法从文件夹中删除文件。我陷入了困境,所以任何输入都会受到赞赏。
在dataprocessor.h中:
...
QList<QString> justProcessed;
...

在dataprocessor.cpp文件中

void DataProcessor::onSignal() {
// Will keep running as long as there are files in the spool folder, eating it's way through
bool stillFiles = true;

QDir dir(this->monitoredPath);
dir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
dir.setSorting(QDir::Time);

while(stillFiles) {

    // Have to update on each iteration, since the folder changes.
    dir.refresh();

    QFileInfoList fileList = dir.entryInfoList();
    QString activeFile = "";

    foreach(QFileInfo file, fileList) {

        if((file.suffix() == "txt") && !justProcessed.contains(file.fileName())) {
            // Is a text file. Set for processing and break foreach loop
            activeFile = file.fileName();
            break;
        }

    }

    // If none of the files passed the requirements, then there are no more spl files in the folder.
    qDebug() << activeFile;
    if(activeFile == "") {
        qDebug() << "Finished";
        emit finished();
        stillFiles = false;
    }

    // File is a new file, start processing
    qDebug() << "Selected for processing";
    qDebug() << monitoredPath + "/" + activeFile;
    if(!dir.remove(monitoredPath + "/" + activeFile)) qDebug() << "Could not remove file";

    justProcessed.append(activeFile);

} // While end
}

如果我漏提供了一些信息,请告诉我。


你的打印池服务正在运行吗? - Nejat
如果打印队列正在运行,我认为它会打开文件并阻止删除操作。 - Nejat
可能就是这样了。如果我等待一段时间(我用了4秒),然后列出文件夹中的文件,然后删除它们(没有任何while循环),则文件将被正确列出并且随后删除。如果我去掉4秒的延迟,则只会删除一些文件,并在其他文件上返回错误。 - Nicolai Lissau
@Attaque,正如你所说,你可能“太快”了。在接收到更改通知后,该文件可能仍然被其他应用程序使用。请注意,这可能会影响文件的处理删除(取决于其他应用程序如何使用该文件)。如果你想允许等待其他文件被处理,那么你将不得不使用一个计时器来推迟这些操作。 - deGoot
我会尽快更新这篇文章,以便正确描述它。请不要在问题中更新解决方案。将您的解决方案发布为答案——自己回答问题是可以的! - Kuba hasn't forgotten Monica
显示剩余7条评论
1个回答

0
问题最终被分解成两个问题。其中一个问题是系统速度太快,导致在系统读取和删除文件的同时进行。我通过添加QTimer来解决这个问题,每次从监视的文件夹发出信号时重置它。500毫秒从系统上一次更改足以满足需求。与其像我最初那样不断地使用QFileSystemWatcher读取此文件夹中的文件并将其添加到队列中,我创建了一个函数,在处理文件夹中的文件时静音系统监视器。为了弥补文件监视器的功能,我在处理线程中创建了一个递归循环,以便只要还有文件存在,就会继续读取指定的文件。虽然可以在一个线程中完成这项工作。你们都谈论代码,所以这里是:

信号和槽设置

// Setting up folder monitoring.
watcher.addPath(worker->monitoredPath);
QObject::connect(&watcher, SIGNAL(directoryChanged(QString)), this,
SLOT(updateQueue()));
// Timer
connect(timer, SIGNAL(timeout()), this, SLOT(startProcess()));
connect(this, SIGNAL(processRequest()), thread, SLOT(start()));
...

void MainWindow::updateQueue() {
  // Starts or restarts the call to start process. Prevents multiple signals from
  // many files added at once
  timer->start(500);
}
...
void MainWindow::startProcess() {

  if(!thread->isRunning()) {
    emit processRequest();
    muteWatcher(true);  // From here on a recursive loop in dataprocessor checks
                        // the folder for new files.
  }
  timer->stop();

}

静音文件监视器

void MainWindow::muteWatcher(bool toggle) {
  if(toggle) {
    watcher.removePath(worker->monitoredPath);
  } else {
    watcher.addPath(worker->monitoredPath);
  }
}

处理线程

void DataProcessor::initialize() {
  QDir dir(this->monitoredPath);
  dir.setFilter(QDir::NoDotAndDotDot | QDir::Files);
  dir.setSorting(QDir::Time);

  QList<QString> dFiles;

  foreach(QFileInfo file, dir.entryInfoList()) {

    if(file.suffix().toLower() == "txt") {
        dFiles.append(file.fileName());
    }
  }

  if(dFiles.count() == 0) { // Base case
    emit muteWatcher(false); // Start monitoring the folder again
    emit finished(); // end the thread
    return true;
  }

  // PROCESSING HERE

  initializeLabel();

}

接下来的事情是进入我正在打印的打印机的首选项,以防止该打印机将拍摄文件添加到文件夹中。您可以通过单击“直接打印到打印机”来启用此功能。这解决了我大部分的问题,我能够删除我为了防止程序读取打印机生成的文件而创建的一系列延迟。
希望这能帮助到某些人!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接