2010-05-12 8 views
5

Я пробовал следующий короткий пример, чтобы узнать об ошибке в большей программе, над которой я работаю. Похоже, QFile не поддерживает UNIX (или командный интерпретатор) обозначение для домашнего каталога:Почему QFile не читается из каталога «~»?

#include <QFile> 
#include <QDebug> 

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

Как только я заменить «~» с моим путем реальных домашнего каталога, это работает. Есть ли простой способ обхода - некоторые настройки позволяют? Или мне нужно пойти «уродливым» способом и спросить QDir для домашнего каталога текущего пользователя и добавить его вручную к каждому пути?

Приложение: Понятно, что обычно оболочка выполняет расширение тильды, поэтому программы никогда этого не увидели. Тем не менее это настолько удобно в оболочках unix, что я надеялся, что реализация Qt для доступа к файлу будет включать это расширение.

+3

Это может оказаться полезным для реализации 'оператор/(QDir, зЬй :: строка)', так что вы можете написать 'QDir :: HOMEPATH()/" vimrc"' – MSalters

ответ

3

Это не имеет никакого отношения к поддержке UNIX; расширение тильд в домашний каталог пользователя - это замена, выполняемая оболочкой, поэтому да, вам придется вручную их заменить.

+0

Да, я знаю, что это расширение оболочки. Но это так удобно, что я надеялся, что реализация unix Qt будет поддерживать и расширять тильду. – hurikhan77

0

Взгляните на библиотечную функцию C glob, которая будет делать расширение тильды (и, возможно, расширение подстановки и различные другие функции).

+0

Я предполагаю, что это будет связано с выделением других специальных штрихов, которые я не хочу обсуждать. И я должен обработать несколько записей в возвращаемом списке, так как glob не вернет ни одной строки (хотя список содержит, вероятно, только одну строку). – hurikhan77

+1

Это зависит от вашей ОС; например, OS X имеет флаг GLOB_LIMIT, который позволит вам запрашивать только один результат. Для того, что может быть еще более полезной функцией, попробуйте 'wordexp', который позволяет вам делать большую часть того, что делает оболочка при построении команд. –

8

Почему бы не просто создать вспомогательную функцию, что-то вроде (непроверенные):

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

Более полное решение может быть (опять непроверенной, так как я не имею Qt локально, но компетентный кодировщик должен быть в состоянии для этого:

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

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

    // Special case for current user. 

    if (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, ""); 
    int len = name.indexOf ('/'); 
    if (len == -1) 
     len = name.length() 
    else 
     len--; 
    name = name.left (idx); 

    // Find that user in the passwd file, replace with home directory 
    // if found, then return it. 

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

    return fspec; 
} 
+0

Хотя мне нравится идея, она станет громоздкой при работе с такими случаями, как «~ пользователь» и т. Д. – hurikhan77

+0

В любом случае, ваш код, вероятно, не должен пытаться возиться в другом каталоге пользователя :-) Но, если вы хотите, чтобы полных расширений, вам, вероятно, придется выйти в оболочку, чтобы получить их. Я отвечал только на конкретный случай в вашем вопросе: '' '. Тем не менее, если вам нужна вся гамма, лучше всего изолировать код от этой единственной вспомогательной функции. Если это просто '~ /', используйте то, что я дал. Если это '~ <ничего-else>', найдите другой способ внутри функции, например, запустить подселочку, чтобы получить ее значение. Я не вижу более громоздкого способа делать то, что вы хотите. – paxdiablo

+0

Другими словами, даже если Qt предоставил эту функцию, он, вероятно, будет делать это так, как я предлагаю (хотя, возможно, немного более кросс-платформенный). – paxdiablo