zoukankan      html  css  js  c++  java
  • 从相对路径说开来(从C++到Qt)

    从相对路径说开来(从C++到Qt)

    转载自:http://blog.csdn.net/dbzhang800/article/details/6363165

    在Qt论坛经常看到网友抱怨:

    • QPixmap("dbzhang800.png") 加载图片不成功
    • QFile("dbzhang800.txt") 打开文件失败
    • ...

    遇到这种问题,我一般回答:请注意区分进程的"工作目录 "与程序所在的目录 。但这种回答似乎还是显得太苍白了,既然如此,整理一下吧。

    • 用到了相对路径,你清楚"相对"是相对那个目录的么?
    • 当你抱怨Qt时,你知道它与Qt无关么?
    Qt 是 C++ 的库,我们还是从C++开始看吧(注:你可能会对 用ISO C++实现自己的信号槽(另类的Qt学习) 以及 从 C++ 到 Qt 感兴趣) 。

    相对路径

    刚接触文件操作时,我们应该都写过这种简单的小程序吧:

    #include <stdio.h>
    
    int main()
    {
       FILE * pFile = fopen ("dbzhang800.txt" , "r");
       if (pFile == NULL) {
           perror ("Error opening file");
       } else {
         //do something
         fclose (pFile);
       }
       return 0;
    }

    我们在可执行文件的同级目录下放置dbzhang800.txt文件,然后调用编译器编译程序

    cl abc.cpp

    g++ abc.cpp -o abc

    然后运行程序 abc,一切都很正常,是不?

    可能是这个原因吧,导致很多人误认为 :相对目录相对的就是应用程序所在的目录!

    你有没有没试过:

    |-- dir1/
    |    |-- abc(.exe)
    |    `-- dbzhang800.txt
    |
    `-- dir2/

    如果你在终端(或cmd窗口)中切换目录到 dir2,然后通过 ../dir1/abc 运行程序,你的程序还能找到文本文件么?

    如果你想让它找到,此时文件应该放置到哪个目录?

    工作目录

    遇到相对路径,我们肯定绕不过工作目录(working directory)。它有时也被称为当前工作目录(c urrent w orking d irectory),所有的相对路径都是从工作目录开始解释的。 我们可以通过_chdir 等函数来更改进程的工作目录。

    接前面的例子,如果你真的对工作目录没有感觉,不妨直接输出来自己看看(网络上你可能会看到其他posix等提供的函数,我们只使用ISO C++标准中的函数):

    #include <direct.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    int main( void )
    {
       char* buffer;
       if( (buffer = _getcwd( NULL, 0 )) == NULL ) {
          perror( "_getcwd error" );
       } else {
          printf( "Current Dir: %s /n", buffer);
          free(buffer);
       }
    }
    • 我们调用 _getcwd 来获得当前的工作目录
    • 你可以在终端或cmd中切换到其他目录,通过绝对路径来调用你的这个程序,来观察输出
    • 如果你在linux下,你可以创建启动器,然后启动器中可以设置工作目录
    • 如果你在windows下,你可以为其创建快捷方式,快捷方式属性中可以设置/修改工作目录

    进程内修改工作目录

    看个无聊的例子:

    #include <stdio.h>
    #include <direct.h>
    
    int main()
    {
        _chdir("c://temp");
    
       FILE * pFile = fopen ("dbzhang800.txt" , "r");
       if (pFile == NULL) {
           perror ("Error opening file");
       } else {
         //do something
         fclose (pFile);
       }
       return 0;
    }
    • 使用  _chdir   修改工作目录

    • 现在,程序将去打开C盘temp目录下的文本文件

    注:_chdir   和  _getcwd 都有对应的宽字符(wchar_t)版本,此处不涉及(如果你要使用宽字符,不妨先考虑看看此文C 源文件内的中文(2) )。

    回到Qt

    Qt 是C++的库,所以上面的东西你完全可以直接用。不过由于Qt提供更好用的东西QDir,我想你应该不会想着在Qt中使用前面提到的C、C++的中函数。

    注意:如果你要操作的文件是只读的,而且程序编译完成后这些文件不需要变化,那么请首先考虑采用Qt的资源文件.qrc(本文不涉及这部分)。

    下面:我们不妨看看前两个函数在Qt中的等价物。

    获得工作目录

    如果你对工作目录依然不熟悉,使用相对路径出现问题时,请首先考虑使用下列语句:

    qDebug()<<QDir::currentPath();

    看看和你预想的是否相符。

    修改工作目录

    • 你很少需要这个操作
    • 如果你用到了,请注意
    bool QDir::setCurrent ( const QString & path ) [static]
    • 而不是
    bool QDir::cd ( const QString & dirName )
    bool QDir::cdUp ()
    void QDir::setPath ( const QString & path )

    程序所在目录

    如何知道你程序自己在那个目录下,这是一个和平台相关的问题(ISO C、C++ 目前似乎还不能告诉我们答案)。幸好Qt提供了很好的封装了:

    QString QCoreApplication::applicationDirPath () [static]

    如果你想使用相对路径访问和可执行程序的同目录下的文件,你可以将工作目录设置成该目录!

    或者(这应该是更好点的方法),用该目录和你的相对路径先直接组合成绝对路径再使用。

    可是 ,你有没有这个问题:当我们在windows下使用Qt的时候,生成的可执行程序会在debug或release目录下,我们要访问的文件在 project.pro 文件所在目录(或其子目录)下。这可怎么办是好?

    一个有用的函数

    如果你想访问工程目录下的doc/dbzhang800.txt文件:

    |-- project.pro
    |-- doc/
    |     `-- dbzhang800.txt
    |
    |-- release/
    |     `-- abc.exe
    |
    `-- debug/
          `-- abc.exe

    直接

    QFile(doc/dbzhang800.txt);

    好用么?如果在QtCreator 等环境下运行,一般可以工作,可是,进到debug下双击,却不工作了(不要告诉我你看了上面内容还不知道原因哈)。

    问题的解决方案来自C++ GUI Qt4 编程一书,我相信你肯定见过这个函数:

    QDir directoryOf(const QString &subdir)
    {
        QDir dir(QApplication::applicationDirPath());
    
    #if defined(Q_OS_WIN)
        if (dir.dirName().toLower() == "debug"
                || dir.dirName().toLower() == "release"
                || dir.dirName().toLower() == "bin")
            dir.cdUp();
    #elif defined(Q_OS_MAC)
        if (dir.dirName() == "MacOS") {
            dir.cdUp();
            dir.cdUp();
            dir.cdUp();
        }
    #endif
        dir.cd(subdir);
        return dir;
    }

    这个函数怎么用?   我们只需要:

    QFile(directoryOf("doc").absoluteFilePath(dbzhang800.txt));

    shadow build

    qmake 很早就提供shadow build功能,但也就QtCreator默认使用了该功能以后,大部分人才开始注意到它。

    |-- project-sources/
    |       |-- project.pro
    |       `-- main.cpp
    |
    |-- build-vs2008/
    |       |-- Debug/
    |       |    `-- main.exe
    |       `-- Release/
    |            `-- main.exe 
    |-- build-vs2005/
    |-- build-mingw/
    |-- build-symbian/
    |-- build-dbzhang800/
    |-- ...

    这儿没有神奇之处,只不过一般资料上介绍qmake都是这样说的:

    qmake project.pro
    make

    而 qtcreator 是这么做的

    cd ../build-vs2008
    qmake ../project-sources/project.pro
    make

    这种情况下,我们一般需要将一些文件拷贝到构建目录下,具体可参考  浅谈 qmake 之 shadow build   最后给的一段代码

    http://blog.csdn.net/wsh6759/article/details/7432295

  • 相关阅读:
    Android9.0/8.1/6.0 默认给系统 app 授予所有权限
    Git——处理Warning: CocoaPods is installed but broken. Skipping pod install. You appear to have CocoaPods installed but it is not working.
    Git——error: RPC failed; curl 56 LibreSSL SSL_read:报错处理
    Git——To install: sudo gem install cocoapods 报错处理
    Xcode——清除缓存相关文件
    vue —— 拉取远程仓库在本地开发
    vue —— mac中配置Node、NPM环境
    Flutter——常见报错处理
    Git——从githup上克隆下一个完整的项目操作步骤
    Git——rebase实际操作遇到的问题
  • 原文地址:https://www.cnblogs.com/findumars/p/5843429.html
Copyright © 2011-2022 走看看