相对路径和绝对路径和(从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;
}
使用gcc编译后:
g++ abc.cpp -o abc
然后运行程序 abc,一切都很正常。但如果执行程序abc和dbzhang800.txt不在同一个目录下,此时程序将无法找到文件。
工作目录(Current Working Directory)
=相对路径,肯定绕不过工作目录(working directory),它有时也被称为当前工作目录,所有的相对路径都是从工作目录开始解释的。
一般来说,每个进程都有一个与之相关联的分级文件系统(hierarchical file system)下的目录,称之为该进程的当前工作目录。默认为程序启动的目录或者父进程启动此应用程序时所在的目录。
但是当前工作目录是可以通过程序进行设置:
ISO C标准
#include <dir.h>
int chdir(const char *path); //设置工作目录
char *getcwd(char *buf, int n); //读取工作目录
Qt中相关函数
[static] bool QDir::setCurrent(const QString &path)
[static] QString QDir::currentPath()
程序所在目录
ISO C标准
//获取当前程序所在路径
char pszFileName[MAX_PATH] = { 0 };
GetModuleFileName(NULL, pszFileName, MAX_PATH);
Qt中相关函数
[static] QString QCoreApplication::applicationDirPath()
如果想使用相对路径访问和可执行程序的同目录下的文件,你可以将工作目录设置成该目录
一个有用的函数
当我们在windows下使用Qt的时候,生成的可执行程序会在debug或release目录下,我们要访问的文件在 project.pro 文件所在目录(或其子目录)下。此时如何使用相对路径?
如果你想访问工程目录下的doc/dbzhang800.txt文件
|-- project.pro
|-- doc/
| | -- dbzhang800.txt
|
|-- release/
| | -- abc.exe
|
|-- debug/
|-- abc.exe
直接使用下发的方式肯定是无法同时兼容debug和release两种情况
QFile(doc/dbzhang800.txt)
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));
QResource资源文件的路径
|-- project.pro
|-- images/
| | -- landscape.png
|
|-- styles.qss
|
|-- resource.qrc
|
|-- main.cpp
resource.qrc 配置方式如下:
<RCC>
<qresource prefix="/menu">
<file>images/landscape.png</file>
</qresource>
<qresource prefix="/qss">
<file>styles.qss</file>
</qresource>
</RCC>
则可以分别如下使用:
QIcon icon(":/menu/images/landscape.png");
QFile f(":/qss/styles.qss");
以冒号:开头的路径始终被视为绝对路径,因为它们表示 QResource。
当然,如果在main.cpp中,通过QDir::setCurrent()将当前路径设置为project.pro对于目录;
QIcon icon("images/landscape.png");
QIcon icon("./images/landscape.png");
QFile f("styles.qss");
QFile f("./styles.qss");
shadow build
shadow build 就是将源码路径和构建路径分开(也就是生成的makefile文件和其他产物都不放到源码路径),以此来保证源码路径的清洁。
qt creator默认使用 shadow build构建项目
|-- project-sources/
| |-- project.pro
| |-- main.cpp
|
|-- build-vs2008/
| |-- Debug/
| | |-- main.exe
| |-- Release/
| |-- main.exe
|-- build-vs2005/
|-- build-mingw/
|-- build-symbian/
|-- build-dbzhang800/
|-- ...
shadow build的实现
- Makefile out-of-source
qt creator实际采用如下类似方式将Makefile生成在指定的目录
cd ../build-vs2008
qmake ../project-sources/project.pro
make
- 中间产物的out-of-source
通过在pro(pri.)文件中,增加如下配置,实现编译中间产物的out-of-source
环境变量 | 含义 |
---|---|
DESTDIR = $$PWD/bin | 目标文件放置位置 |
DLLDESTDIR = $$[QT_INSTALL_BINS] | win下拷贝动态库到qt安装路径 |
MOC_DIR = $$PWD/temp | moc的产物放置何处 |
RCC_DIR = $$PWD/temp | rcc的产物放置何处 |
UI_DIR = $$PWD/temp | uic的产物放置何处 |
OBJECTS_DIR = $$PWD/temp | 编译器生成的.o(.obj)等文件放置 |
pro文件中支持的变量
PWD | 使用该变量的文件(.pro 或 .pri)所在目录,注意对比下一个 |
_ PRO_FILE_PWD_ | pro文件所在目录(注意:即使它用在pri文件内,也是指代的包含它的pro文件所在的目录) |
_ PRO_FILE_ | pro文件的全路径 |
OUT_PWD | 生成的makefile文件所在路径,和_PRO_FILE_PWD_对应 |
当不使用shadow build构建时,OUT_PWD 和 PRO_FILE_PWD 是相同的,据此,我们可以判断采用了何种构建方式,进而采用不同的动作:
!contains(_PRO_FILE_PWD_, $${OUT_PWD}) {
#do something when using shadow build
}
#直接使用equals更好一些,但是manual对此没有任何说明(所以我不清楚你的qmake对此是否支持,至少Qt4.5以后都是支持的)
!equals(_PRO_FILE_PWD_, OUT_PWD) {
#do something when using shadow build
}
采用out-of-source构建时,我们可能需要将一些文件从源码目录拷贝到构建目录下,用cmake时,这个很容易做到,但在qmake下,似乎缺少通用的方式,一个简单的demo如下:
FILES_COPY_SRC = $$SOURCES /
dbzhang800.txt /
images/abc.png /
i18n/abcd.qm
win32{
COPY = copy /y
MKDIR = mkdir
}else{
COPY = cp
MKDIR = mkdir -p
}
!equals(_PRO_FILE_PWD_, OUT_PWD) {
for(f, FILES_COPY_SRC){
dist_file = $$OUT_PWD/$$f
dist = $$dirname(dist_file)
win32:dist = $$replace(dist, /, \\) #windows下,必须先将路径分割符由“/”替换成 “/”
!exists($$dist):system($$MKDIR $$dist) #目标目录不存在,创建目录
!exists($$dist_file):system($$COPY $$f $$dist) #目标文件不存在,拷贝文件
}
}
本文参考下面链接整理:
原文链接:https://blog.csdn.net/dbzhang800/article/details/6343838
原文链接:https://blog.csdn.net/dbzhang800/article/details/6363165