`
gaofen100
  • 浏览: 1243475 次
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多

在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 最后给的一段代码

分享到:
评论

相关推荐

    QT c++ dijkstra最短路径工程源码

    QT C++实现Dijkstra最短路径算法的工程源码提供了在图形用户界面(GUI)下解决图论问题的一个实例。这个项目结合了QT框架的强大功能和C++编程语言的灵活性,帮助开发者直观地理解和应用Dijkstra算法。以下是相关知识点...

    银行管理系统QT(c++)

    银行管理系统QT(c++)银行管理系统QT(c++)银行管理系统QT(c++)银行管理系统QT(c++)银行管理系统QT(c++)银行管理系统QT(c++)银行管理系统QT(c++)银行管理系统QT(c++)银行管理系统QT(c++)银行管理系统QT(c++)银行管理...

    基于Qt使用C++实现图书管理系统源码.zip

    基于Qt使用C++实现图书管理系统源码 基于Qt使用C++实现图书管理系统源码 基于Qt使用C++实现图书管理系统源码 基于Qt使用C++实现图书管理系统源码 基于Qt使用C++实现图书管理系统源码 基于Qt使用C++实现...

    C++和QT实现的交通路径规划系统

    本系统采用C++实现,界面部分采用的是QT设计,充分利用了迪杰斯特拉算法、佛洛依德算法、图的深度优先遍历算法等最短路径算法,数据结构采用了vector、优先队列、栈、邻接矩阵等等,对于想要学习数据结构和QT的同学...

    C++ Qt5 范例开发大全,qt5开发及实例,QT

    总的来说,《C++ Qt5 范例开发大全》是一本全面覆盖Qt5开发的教程,它以实例为引导,通过深入浅出的讲解,帮助读者全面掌握Qt5框架,无论你是初涉GUI编程还是寻求进阶,都能从中受益匪浅。通过阅读和实践书中的例子...

    QT linux c++界面编程

    QT linux c++界面编程QT linux c++界面编程QT linux c++界面编程QT linux c++界面编程QT linux c++界面编程

    Qt教程.pdf ,从最全面认识Qt(C++学习)

    2012年,Qt被Digia公司收购,这一系列的变迁也反映了Qt从诞生到现在的发展历史。 Qt拥有丰富的模块化功能,包括网络编程、数据库操作、多线程处理、绘图和绘图设备、文件系统操作等。它也提供了对各种类型窗口的...

    Qt 5.9 C++开发指南-Qt核心特点源码

    **Qt 5.9 C++ 开发指南:深入理解Qt核心特点与源码解析** Qt是一个流行的开源跨平台应用程序开发框架,广泛应用于桌面、移动和嵌入式系统。Qt 5.9是其一个重要的版本,它在稳定性和性能上都有显著提升,同时也引入...

    C++ QT 显示图片

    本篇文章将详细讲解如何利用Qt库在C++中实现图片的加载,包括从本地和网络加载图片。 首先,我们要了解Qt中的QImage类,它是Qt图形视图框架的一部分,用于处理图像数据。QImage支持多种图像格式,如JPEG、PNG、BMP...

    C++GUI Qt4编程源代码

    C++ GUI Qt4编程是面向开发人员的一个关键领域,特别是对于那些希望创建具有图形用户界面的应用程序的人来说。Qt4是一个强大的跨平台应用程序开发框架,由Qt公司(现在是The Qt Company)开发,支持Windows、Linux、...

    C++_GUI_Qt4编程(第二版)_C++GUIQt4编程_QT_

    通过《C++_GUI_Qt4编程(第二版)》,读者不仅能掌握Qt4的基本用法,还能了解到更高级的特性和实践,为成为熟练的Qt开发者打下坚实基础。无论你是初学者还是有一定经验的开发者,这本书都能提供宝贵的指导和启发。

    QT C++创建HTTP服务,C++快速简单创建web服务器 QT快速提供Resful接口 C++创建Resful服务

    QT C++创建HTTP服务,C++快速简单创建web服务器 QT快速提供Resful接口 C++创建Resful服务 C++快速提供get、post服务 C++实现HTTP服务 搭建HTTP服务 https://blog.csdn.net/weijia3624/article/details/139236610 ...

    C++ QT5教程 开发大全和教程 完整

    QT5不仅包含C++库,还支持QML(Qt Meta Language)进行UI设计,使得开发者能够构建用户界面更加直观和现代。在"QT5开发大全 教程"中,我们可以期待涵盖以下几个核心知识点: 1. **QT5基础知识**:了解QT5的基本架构...

    QT5 C++ GUI 编程指南

    最后,压缩包中的"QT C++"可能包含QT开发相关的源代码示例或项目模板,这对于初学者来说是一份宝贵的资源,通过实践这些示例,可以更好地理解和运用QT5.9的C++ GUI编程技术。 总之,QT5 C++ GUI编程指南是一份全面...

    Qt+C++校园最短路径.zip

    根据校园各主要生活、学习、活动等场所、地点,设计并实现基于校园各场所之间的最短路径漫游。 要求: (1)掌握数据结构的输入/输出; (2)设计与实现校园各主要场所之间的最短路径算法; (3)根据场所之间的...

    Qt5.9C++书本代码资源.zip

    这个压缩包中可能包含了各种Qt5.9和C++结合的示例代码,可能是从简单的窗口应用到复杂的多线程、数据库交互或者网络通信的案例。这些代码实例可以帮助开发者快速上手Qt的API,理解如何使用Q widgets创建用户界面,...

    C++Qt5开发实例大全

    总的来说,《C++ Qt5 开发实例大全》是一本全面且深入的教程,适合从初学者到有经验的开发者阅读。通过实际的代码示例,读者可以快速掌握Qt5的使用,从而能够高效地开发出功能丰富的桌面应用程序。无论是窗体设计、...

    Qt5 C++ GUI Programming Cookbook.rar_C++_QT5_Qt5 C++ GUI

    Qt5 C++ GUI Programming Cookbook.pdf

    Qt5.9 C++开发指南.pdf 及章节代码

    **Qt5.9 C++开发指南** Qt是一个跨平台的应用程序开发框架,广泛用于创建桌面、移动和嵌入式应用程序。在Qt5.9版本中,它提供了许多增强的功能和改进,使得C++开发者能够更加高效地构建用户界面和应用程序。本指南...

    Qt中的C++技术

    总的来说,Qt中的C++技术融合了C++的面向对象特性、模板、异常处理、智能指针、命名空间和元对象系统等多种技术,提供了一个高效、灵活且功能丰富的开发环境。通过深入理解和熟练掌握这些技术,开发者可以创建出高...

Global site tag (gtag.js) - Google Analytics