从相对路径说开来(从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
从相对路径说开来(从C++到Qt)的更多相关文章
- 转:C# WinForm获取 当前执行程序路径的几种方法
1.获取和设置当前目录的完全限定路径. string str = System.Environment.CurrentDirectory; Result: C:xxxxxx 2.获取启动了应用程序的可 ...
- C#当前应用程序路径及环境变量
一.获取当前文件的路径 1. System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName 获取模块的完整路径.可获得当前执行的 ...
- C#- WinForm获取 当前执行程序路径的几种方法
1.获取和设置当前目录的完全限定路径.string str = System.Environment.CurrentDirectory;Result: C:xxxxxx 2.获取启动了应用程序的可执行 ...
- Jexus-5.6.3使用详解、Jexus Web Server配置
一.Jexus Web Server配置 在 jexus 的工作文件夹中(一般是“/usr/jexus”)有一个基本的配置文件,文件名是“jws.conf”. jws.conf 中至少有 Site ...
- Jexus-5.6.3使用详解
一.Jexus Web Server配置 在 jexus 的工作文件夹中(一般是"/usr/jexus")有一个基本的配置文件,文件名是"jws.conf".j ...
- jexus
Jexus web server V5.1 安装配置要点 一.Jexus简介:Jexus web server for linux 是一款基于.NET兼容环境,运行于Linux/unix操作系统之上, ...
- C/C++ 跨平台交叉编译、静态库/动态库编译、MinGW、Cygwin、CodeBlocks使用原理及链接参数选项
目录 . 引言 . 交叉编译 . Cygwin简介 . 静态库编译及使用 . 动态库编译及使用 . MinGW简介 . CodeBlocks简介 0. 引言 UNIX是一个注册商标,是要满足一大堆条件 ...
- 用sublime编译C++的方法
sublime代码高亮这么好看,怎么能不用sublime敲代码呢: ) 本人用的版本是sublime Text3中文版 在网上查了查,自己的sublime现在也能编译C++了,设置步骤如下: 1.找到 ...
- 网络接口 使用NSURLConnection完成Get和Post方法
网络接口 使用NSURLConnection完成Get和Post方法 什么是URL: URL就是统一资源定位器(UniformResourceLocator:URL).通俗地说,它是用来指出某一项信息 ...
随机推荐
- 为Android GridView 设置行背景
经常有这样的需求,你的功能图标要像一个个物品,摆放在书架上,像这样: 我的思路比较简单,重载GridView,在他绘制子视图前,先把背景绘制完成 1 2 3 4 5 6 7 8 9 10 11 12 ...
- Phonegap(Cordova)3.4 + Android 环境搭建
PhoneGap是一个用基于HTML.CSS和JavaScript的,创建移动跨平台移动应用程序的高速开发平台. 它使开发人员可以利用iPhone,Android,WP7等多 ...
- systemtap [主设备号,次设备好,inode]监控文件
SystemTap 是监控和跟踪运行中的linux 内核的操作的动态方法,SystemTap 应用:对管理员,SystemTap可用于监控系统性能,找出系统瓶颈,而对于开发者,可以查看他们的程序运行时 ...
- Java NIO类库Selector机制解析--转
一. 前言 自从J2SE 1.4版本以来,JDK发布了全新的I/O类库,简称NIO,其不但引入了全新的高效的I/O机制,同时,也引入了多路复用的异步模式.NIO的包中主要包含了这样几种抽象数据类型: ...
- [转] nginx 开启gzip压缩--字符串压缩比率很牛叉
http://www.cnblogs.com/dasn/articles/3716055.html 刚刚给博客加了一个500px相册插件,lightbox引入了很多js文件和css文件,页面一下子看起 ...
- SA密钥长度、明文长度和密文长度
本文介绍RSA加解密中必须考虑到的密钥长度.明文长度和密文长度问题,对第一次接触RSA的开发人员来说,RSA算是比较复杂的算法,RSA的复杂度是因为数学家把效率和安全也考虑进去的缘故. 本文先只谈密钥 ...
- PHP中的function函数详解
PHP函数,在PHP中函数起到一个不可分割的重要部分,很多功能实现都要用到函数,PHP的最大的威力就来源于函数! 在PHP中内建函数至少有上千个函数.这些内建函数了解就行了,官方文档里面有函数大全:传 ...
- Java使用poi对Execl简单_读_操作
public class ReadExecl { // private final String XLSX = ".xlsx"; // 2007以上版本 // private fi ...
- (转)修改ECSHOP前后台的title中的ecshop
前台部分: 1:去掉头部TITLE部分的ECSHOP演示站 Powered by ecshop 前者在后台商店设置 - 商店标题修改 后者打开includes/lib_main.php $page_t ...
- angularjs modal 嵌套modal的问题
anguarjs中当遇到modal嵌套modal的时候,比如一个modal弹出啦一个modal1,关闭modal1后,modal本身的关闭功能失效,那么需要$modal来生命弹出的modal1并且关闭 ...