83

How do I check whether a file exists in a given path or not in Qt?

My current code is below:

QFile Fout("/Users/Hans/Desktop/result.txt");

if(!Fout.exists()) 
{       
  eh.handleError(8);
}  
else
{
  // ......
}

But when I run the code it is not giving the error message specified in handleError even though the file I mentioned in the path does not exist.

Grade 'Eh' Bacon
  • 3,773
  • 4
  • 24
  • 46
user1322915
  • 1,211
  • 2
  • 13
  • 10

5 Answers5

110

(TL;DR at the bottom)

I would use the QFileInfo-class (docs) - this is exactly what it is made for:

The QFileInfo class provides system-independent file information.

QFileInfo provides information about a file's name and position (path) in the file system, its access rights and whether it is a directory or symbolic link, etc. The file's size and last modified/read times are also available. QFileInfo can also be used to obtain information about a Qt resource.

This is the source code to check whether a file exists:

#include <QFileInfo>

(don't forget to add the corresponding #include-statement)

bool fileExists(QString path) {
    QFileInfo check_file(path);
    // check if file exists and if yes: Is it really a file and no directory?
    if (check_file.exists() && check_file.isFile()) {
        return true;
    } else {
        return false;
    }
}

Also consider: Do you only want to check if the path exists (exists()) or do you want to also make sure that this is a file and not a directory (isFile())?

Be careful: The documentation of the exists()-function says:

Returns true if the file exists; otherwise returns false.

Note: If file is a symlink that points to a non-existing file, false is returned.

This is not precise. It should be:

Returns true if the path (i.e. file or directory) exists; otherwise returns false.


TL;DR

(with shorter version of the function above, saving a few lines of code)

#include <QFileInfo>

bool fileExists(QString path) {
    QFileInfo check_file(path);
    // check if path exists and if yes: Is it really a file and no directory?
    return check_file.exists() && check_file.isFile();
}

TL;DR for Qt >=5.2

(using exists as a static which was introduce in Qt 5.2; the docs say the static function is faster, though I'm not sure this is still the case when also using the isFile() method; at least this is a one-liner then)

#include <QFileInfo>

// check if path exists and if yes: Is it a file and no directory?
bool fileExists = QFileInfo::exists(path) && QFileInfo(path).isFile();
mozzbozz
  • 3,052
  • 5
  • 31
  • 44
  • 4
    Just a suggestion, the code in function `bool fileExists(const QString &path)` could be further simplified to: `return checkFile.exists() && checkFile.isFile(); `@mozzbozz – Dreamer Apr 04 '16 at 20:54
  • @Dreamer Thanks for your comment. Of course you are right, although it is also a matter of taste. I've added your version, too (I will leave the longer version here as it might be easier to follow for beginners). – mozzbozz Apr 12 '16 at 21:39
  • 1
    @kayleeFrye_onDeck Be careful, your edit is not really correct. It is right that the docs say that the static function is faster. However, the docs are quite unprecise about what the function really does. The exists function (static or not) only checks if the path exists, not if there is a file. So, if there is a directory with the given path, then your suggestion will also return `true`! (just tested it on my system with Qt 5.10) – mozzbozz Apr 20 '18 at 13:12
  • @mozzbozz can you share a snippet with that behavior on GistHub? I just tested it with Qt 5.6, and the `static` function for `exists` only returns true on my file-check when the file actually exists, not just the directory. Or did I misunderstand you? Mine was pretty lean: `bool hasit = QFileInfo::exists("C:\\myfile.tst");` – kayleeFrye_onDeck Apr 23 '18 at 17:14
  • 1
    @kayleeFrye_onDeck Sure (tested with Qt 5.6 under Windows): https://gist.github.com/mozzbozz/2e83d7e3452a07fa817980403c42eade --> Yes, I think this is a misunderstanding. I meant the `exists` function (`static` or not) returns `true` if the given path is a directory. However the question was "How do I check whether a *file* exists" (and not *directory*). Take a look at the linked code snippet, I hope that explains what I mean. – mozzbozz Apr 30 '18 at 17:41
  • Deceptive Qt documentation is deceptive :( https://i.imgur.com/NaewOBU.png – kayleeFrye_onDeck Apr 30 '18 at 18:29
  • 1
    But wait, it gets _worse_ haha: https://i.imgur.com/5Hds4kA.png _**"file"**_ *sigh* – kayleeFrye_onDeck Apr 30 '18 at 18:34
  • Wow, _this_ is genuinely aggravating. You'd think the `QFile` library would at least ensure a file is a file... https://gist.github.com/the-nose-knows/97fa752d49db56946ceede724d2a2c39 ; thanks for watching out for us, mozzbozz! – kayleeFrye_onDeck Apr 30 '18 at 18:44
15

You can use the QFileInfo::exists() static method:

#include <QFileInfo>
if(QFileInfo::exists("C:\\exampleFile.txt")){
    //The file exists
}
else{
    //The file doesn't exist
}

If you want it to return true only if the file exists and false if the path exists but is a folder, you can combine it with QDir::exists():

#include <QFileInfo>
#include <QDir>
QString path = "C:\\exampleFile.txt";
if(QFileInfo::exists(path) && !QDir(path).exists()){
    //The file exists and is not a folder
}
else{
    //The file doesn't exist, either the path doesn't exist or is the path of a folder
}
Donald Duck
  • 8,409
  • 22
  • 75
  • 99
  • Be careful: If you give a path to a directory, your source code will also return `true`, even though it is "only" a file. The OP asked to check for a file, not a path. – mozzbozz Apr 20 '18 at 13:31
  • 1
    @mozzbozz If you want it to return `false` if the path exists but is a folder, you can do `QFileInfo(path).exists() && !QDir(path).exists()`. I've edited my answer to add that. – Donald Duck Apr 21 '18 at 09:18
8

The code you've posted is correct. Chances are that something else is wrong.

Try putting this:

qDebug() << "Function is being called.";

inside of your handleError function. If the above message prints, you know something else is the problem.

Anthony
  • 8,570
  • 3
  • 38
  • 46
3

That's how I check if the database exists:

#include <QtSql>
#include <QDebug>
#include <QSqlDatabase>
#include <QSqlError>
#include <QFileInfo>

QString db_path = "/home/serge/Projects/sqlite/users_admin.db";

QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(db_path);

if (QFileInfo::exists(db_path))
{
    bool ok = db.open();
    if(ok)
    {
        qDebug() << "Connected to the Database !";
        db.close();
    }
}
else
{
    qDebug() << "Database doesn't exists !";
}

With SQLite it's difficult to check if the database exists, because it automatically creates a new database if it doesn't exist.

fredmaggiowski
  • 2,232
  • 3
  • 25
  • 44
Essetee
  • 65
  • 1
  • 2
1

I would skip using anything from Qt at all, and just use the old standard access:

if (0==access("/Users/Hans/Desktop/result.txt", 0))
    // it exists
else
    // it doesn't exist
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • @Styne666: Every compiler of which I'm aware on Windows supports `access` -- certainly MS, and the gcc ports. Intel uses the MS library, which supports it, and Comeau uses the library of the back-end compiler. – Jerry Coffin Apr 23 '12 at 07:18
  • Thank you for making me do my research. I accept this may appear to work, but taking into account [the comments on this answer](http://stackoverflow.com/a/230068/594137) I still think sticking with Qt's options (if you have a Qt project) is a better solution. – Samuel Harmer Apr 23 '12 at 07:31
  • 2
    @Styne666: I'm not at all sure Qt provides anything to fix the problem for setuid/setgid programs, which seems to be about the only one that matters. They argued about the meaning of "cross platform" and which standards to care about, but if we only care about the platforms supported by Qt, those are mostly moot points. – Jerry Coffin Apr 23 '12 at 07:36