ScrawnySquirrel
ScrawnySquirrel

Reputation: 125

Properly storing QFiles in a collection

What is the best way to store multiple QFile in a collection? Would be best to use QList, array, or vectors?

I want to access the element of the collection as a QFile and not QFile*.

I'm trying to read a directory in Qt and store all the files in a collection. Then print all the file names to the screen.

How I'm reading the directory:

QDirIterator it(p_dir, QStringList() << "*.wav", QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext())
{
    // Put file into collection
}

Currently I'm using QList to store the QFiles:

QList<QFile*> list;

I read that the best way to get file information is to use QFileInfo type. How could I set the QFileInfo file to be the element from my list?

I want to do something like:

QFileInfo info;
QListIterator<QFile*> i(list);
while(i.hasNext()) 
{
    info.setFile(i);
}

But the above gives me: error: no matching function for call to 'QFileInfo::setFile(QListIterator&)' fi.setFile(i);

Upvotes: 0

Views: 579

Answers (3)

Naumann
Naumann

Reputation: 417

I'm currently manipulating QFileInfo based on certain criterian/logics..but if I just filter all the complicated logic, it would be something like

QDir testDir("/home/mypath/to/dir");
QFileInfoList files = testDir.entryInfoList();    // #1. here you may use filters as I'm filtering based on a specific file extension
QFileInfoList myfiles;

for(int index = 0; index < files.size(); ++index)
{
    const QFileInfo& info = files.at(index);
    qDebug() << info.absoluteFilePath() << endl;   
   // #2. I've some sort of filters I used in #1 above that I compares here by utilizing info here, something like 
   //if (info.baseName().contains("anyPattern");
        myfiles.push_back(info);      
}    
// Now you can view whatever you stored    
for (int vw_idx = 0; vw_idx < myfiles.size(); ++vw_idx)
 {
   const QFileInfo& info = files.at(index);
   qDebug() << info.absoluteFilePath() << endl;     
 }  

Upvotes: 0

QFile is not copyable. In C++98, there's generally no way of storing it in a container, unless the container supports in-place construction. I don't know offhand of any such C++98 containers, although writing one wouldn't be all that hard.

In C++11, you can use any container that doesn't need to copy elements and supports emplacement, e.g. std::list:

// https://github.com/KubaO/stackoverflown/tree/master/questions/qfile-list-36391586
#include <QtCore>
#include <list>

void populate(std::list<QFile> & files) {
   QDir dir(QCoreApplication::applicationDirPath());
   for (auto fileName : dir.entryList(QDir::Files)) {
      qDebug() << "adding file" << fileName;
      files.emplace_back(fileName);
   }
}

void iterate(std::list<QFile> & files) {
   for (auto & file : files)
      if (file.open(QIODevice::ReadOnly)) {
         qDebug() << "successfully opened" << file.fileName();
      }
}

int main(int argc, char ** argv) {
   QCoreApplication app(argc, argv);
   std::list<QFile> files;
   populate(files);
   iterate(files);
}

On my system, when run from Qt Creator, the output is:

adding file "main.o"
adding file "Makefile"
adding file "qfile-list-36391586"
successfully opened "main.o"
successfully opened "Makefile"
successfully opened "qfile-list-36391586"

Since QFile is a proper class implementing RAII of system resources, the files will get automatically closed by files::~list, before main returns.

Upvotes: 1

dtech
dtech

Reputation: 49319

Keep in mind QFile inherits QObject, and as such is not copyable or movable. It is common practice to store pointers to such objects in containers rather than the objects themselves. As for which container to use, it doesn't really matter much, but QVector will be the most efficient.

QListIterator is a Java style iterator. So:

QListIterator::QListIterator(const QList<T> & list)

Constructs an iterator for traversing list. The iterator is set to be at the front of the list (before the first item).

The iterator doesn't point to anything, if you want to get the actual object, use i.next() to give you a QFile* which you then will have to dereference, since setFile() takes in a QFile &, not a QFile *.

Upvotes: 1

Related Questions