Search code examples
c++qtqtcoreqfileqdir

Display and read all files in directory


I am trying to print out the file names of all files in a directory. However some files do not show up or cannot be opened.

If I restart the program, the files that previously couldn't be opened are in fact opened and displayed. What is going on?

This is my code:

 QDirIterator iterator(dir.absolutePath(), QDirIterator::Subdirectories);
       while (iterator.hasNext()) {
          iterator.next();



              QFile file(iterator.next());

               if ( file.open( QIODevice::ReadOnly ) ) {
                     qDebug() << QFileInfo(file).fileName() << endl;


               } else {
                   qDebug() << "Can't open " << QFileInfo(file).fileName() << endl;
               }
       }

Solution

  • There is one issue here:

     iterator.next();
     QFile file(iterator.next());
     if ( file.open( QIODevice::ReadOnly ) ) {
    

    You are trying to advance the iterator twice inside the loop. That means that you can potentially loop through the last element which will represent an invalid file which then will fail for obvious reasons.

    Depending on the content of the folder, i.e. whether it is changing slightly for the next run, i.e. one file is added or removed, this loop may "work" for the next time, i.e. all the files it tries to open will be opened, but it would have still skipped files in its form.

    The proper fix is the remove this line from the iteration:

    iterator.next();
    

    Therefore, your whole code would be this for your convenience:

    QDirIterator iterator(dir.absolutePath(), QDirIterator::Subdirectories);
    while (iterator.hasNext()) {
        QFile file(iterator.next());
        if ( file.open( QIODevice::ReadOnly ) )
            qDebug() << "Opened:" << file.fileName() << endl;
        else
            qDebug() << "Can't open " << file.fileName() << file.errorString() << endl;
    }
    

    At least two things to note as per comments:

    • You can use the errorString() method for getting more information in such cases.

    • You do not need to construct QFileInfo to get the filename. The QFile object already has a method for that.. The problem is that you are iterating recursively, and as such, you print out only the basenames without knowing where the files reside. You could also display the same file name multiple times if there are files in different subdirectories with the same name.