Home > Mobile >  QProcess to extract file using 7zip as subprocess
QProcess to extract file using 7zip as subprocess

Time:04-28

I have a use case in an application using C and Qt (on windows 10). The application uses 7zip.exe as a subprocess to uncompress the files in a selected folder. I need to use QProcess to extract files.

The code I came up with is as shown below.

     MainWindow.h
QStringList zipFiles;

MainWindow.cpp

void MainWindow::on_browseButton_clicked()
{
        directory = QFileDialog::getExistingDirectory(this);
        if(recursiveOperation){
            QDirIterator it(directory.canonicalPath(), QStringList() << "*.zip" <<  "*.7z", QDir::Files, QDirIterator::Subdirectories);
             ui->outputLogResultList->addItem("File selected to uncompress");
             ui->outputLogResultList->addItem("-----------------------------");
            while (it.hasNext()){
                QString file = it.next();
                ui->outputLogResultList->addItem(file);
                zipFilesWithRecursion.append(file);
            }

        }else{
            zipFilesWithoutRecursion = directory.entryList(QStringList() << "*.zip"<< "*.7z", QDir::Files);
            qDebug() << zipFilesWithoutRecursion;

            foreach(QString filename4, zipFilesWithoutRecursion) {
                     qDebug() << "inside loop";
                    zipFilesWithCompletePath.append( QString(directory.canonicalPath() "/%1").arg(filename4));
                }



                qDebug() << "without recursion";
                qDebug() << zipFilesWithCompletePath;
        }
}



void MainWindow::unZipFile()
{
    int numberOfFiles;
    if(recursiveOperation){
        numberOfFiles = zipFilesWithRecursion.size();
        foreach(QString filename3, zipFilesWithRecursion) {
            QStringList queryArguments;
            queryArguments << "x";
                  qDebug() << filename3;
                  queryArguments <<""""  filename3  """";
                  queryArguments << "-o" directory.canonicalPath() "/output" QString().setNum(numberOfFiles);
                  qDebug() << queryArguments;
                  unZip.setWorkingDirectory(QCoreApplication::applicationDirPath());
                  unZip.start("7za.exe", queryArguments);
                  numberOfFiles--;
              }
        numberOfFiles = 0;
    }else{
        numberOfFiles = zipFilesWithCompletePath.size();
        foreach(QString filename3, zipFilesWithCompletePath) {
            QStringList queryArguments;
            queryArguments << "x";
                  qDebug() << filename3;
                  queryArguments <<""""  filename3  """";
                  queryArguments << "-o" directory.canonicalPath() "/output" QString().setNum(numberOfFiles);
                  qDebug() << queryArguments;
                  unZip.setWorkingDirectory(QCoreApplication::applicationDirPath());
                  unZip.start("7za.exe", queryArguments);
                  numberOfFiles--;
              }
        numberOfFiles = 0;
    }


}

The code run correctly, but after processing the first file, it does not process any other files and displays the state saying "QProcess::start: Process is already running" The output segment is as follows.

Warning: QT_DEVICE_PIXEL_RATIO is deprecated. Instead use:
   QT_AUTO_SCREEN_SCALE_FACTOR to enable platform plugin controlled per-screen factors.
   QT_SCREEN_SCALE_FACTORS to set per-screen DPI.
   QT_SCALE_FACTOR to set the application global scale factor.
("SemiFinal.zip", "temata_vskp_-_podklady_pro_zadani_vskp(10).zip")
inside loop
inside loop
without recursion
("F:/taskPractiseDirectoryForQt/SemiFinal.zip", "F:/taskPractiseDirectoryForQt/temata_vskp_-_podklady_pro_zadani_vskp(10).zip")
"F:/taskPractiseDirectoryForQt/SemiFinal.zip"
("x", "F:/taskPractiseDirectoryForQt/SemiFinal.zip", "-oF:/taskPractiseDirectoryForQt/output2")
"F:/taskPractiseDirectoryForQt/temata_vskp_-_podklady_pro_zadani_vskp(10).zip"
("x", "F:/taskPractiseDirectoryForQt/temata_vskp_-_podklady_pro_zadani_vskp(10).zip", "-oF:/taskPractiseDirectoryForQt/output1")
QProcess::start: Process is already running

The folder has 2 .zip files, My question is why second file is not getting processed.

CodePudding user response:

You have to wait for your QProcess (unZip) to finish, before processing next file or create QProcess instances per file in cycles foreach(QString filename3, zipFilesWithCompletePath) in void MainWindow::unZipFile() method to process them concurrently. If you try to wait unZip.waitForFinished(), your application would be unresponsive for that time as it's main thread would be suspened till process finished. If you want to process files concurrently, QProcess instances should be created in heap, e.g. auto unZipFileProcess = new QProcess(this); and you'll need to write some code to control started processes and wait them all for finish before you close your application, because in that case all processes would be interrupted and killed by their decstructors. To control process state it's proper to connect to QProcess instance signals - errorOccurred and finished. Also these signals should be connected to QProcess' deleteLater slot to avoid memory growth. At this moment you would not need your unZip static or member variable (i don't know how it is declared) at all. In another way, if you do not need to track files processing (wait for finished, report process errors and so on), you can to start processes as detached with static QProcess::startDetached method and not create any QProcess instance at all. So you would not need to control them and synchronize them with your application lifetime. And you defenetly need to redesign your MainWindow::unZipFile() method to avoid code repetitions.

CodePudding user response:

As @Alexey suggested I used

unZip.waitForFinished(3000);

before the end of loop and it worked for me.

  • Related