开发者

Why can't QFile read from the "~" directory?

I've tried the following short example to find out about a bug in a bigger program I am working on. It looks like QFile doesn't support unix (or the shell's) notation for the home directory:

#include <QFile>
#include <QDebug>

int main()
{
        QFile f("~/.vimrc");
        if (f.open(QIODevice::ReadOnly))
        {
                qDebug() << f.readAll();
                f.close();
        }
        else
        {
                qDebug() << f.error();
        }
}

As soon as I replace the "~" with my real home directory path, it works. Is t开发者_JS百科here an easy workaround - some setting to enable? Or do I have to go the "ugly" way and ask QDir for the home directory of the current user and prepend that manually to each path?

Addendum: It's clear that usually the shell performs the tilde expansion so programs would never see that. Still it is so convenient in unix shells that I hoped the Qt implementation for file access would have that expansion included.


You can just create a helper function to do this for you, something like:

QString morphFile(QString s) {
    if ((s == "~") || (s.startsWith("~/"))) {
        s.replace (0, 1, QDir::homePath());
    }
    return s;
}
:
QFile vimRc(morphFile("~/.vimrc"));
QFile homeDir(morphFile("~"));

A more complete solution, allowing for home directories of other users as well, may be:

QString morphFile(QString fspec) {
    // Leave strings alone unless starting with tilde.

    if (! fspec.startsWith("~")) return fspec;

    // Special case for current user.

    if ((fspec == "~") || (fspec.startsWith("~/"))) {
        fspec.replace(0, 1, QDir::homePath());
        return fspec;
    }

    // General case for any user. Get user name and length of it.

    QString name (fspec);
    name.replace(0, 1, "");           // Remove leading '~'.
    int len = name.indexOf('/');      // Get name (up to first '/').
    len = (len == -1)
        ? name.length()
        : len - 1;
    name = name.left(idx);

    // Find that user in the password file, replace with home
    // directory if found, then return it. You can also add a
    // Windows-specific variant if needed.

    struct passwd *pwent = getpwnam(name.toAscii().constData());
    if (pwent != NULL)
        fspec.replace(0, len+1, pwent->pw_dir);

    return fspec;
}

Just one thing to keep in mind, the current solution is not portable to Windows (as per the comments in the code). I suspect this is okay for the immediate question since .vimrc indicates that's not the platform you're running on (it's _vimrc on Windows).

Tailoring the solution to that platform is possible, and indeed shows that the helper-function solution is a good fit since you'll only have to change one piece of code to add that.


It has nothing to do with not supporting UNIX; the expansion of tildes to the user's home directory is a substitution performed by the shell, so yes, you will have to manually replace them.


Please submit a suggestion to the Qt bugtracker.

https://bugreports.qt.io/


Take a look at the C library function glob, which will do tilde expansion (and possibly wildcard expansion and various other functions too).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜