Qt程序使用路径方式和注意事项 原创
Qt程序使用路径方式和注意事项
更多精彩内容 |
---|
👉个人内容分类汇总 👈 |
👉Qt开发经验 👈 |
前言
- 在程序开发中我们会经常使用到路径功能,例如:读取
./
路径下的配置文件,将日志文件、运行数据保存到当前路径,将视频文件保存到系统的视频文件夹下等;- 很多人开发时图方便就使用相对路径,然后用户使用时程序就出问题了,这就需要文件路径指定正确了,否则就会开发不规范,调试两行泪;
- 路径分为相对路径、绝对路径;
- 在Windows下文件/文件夹又有实际路径,快捷方式路径;
- 在Linux下文件/文件夹又有实际路径,软/硬链接路径;
- 程序运行方式有Qt编译运行,双击可执行程序运行,双击快捷方式运行,命令行
./
运行等;- 这些不同的组合就会导致使用的路径存在不同的情况,也决定了你写的程序能不能正常的运行,所以我就整理了一下Qt中使用路径的方式和注意事项,避免以后程序出现问题。
- 实际开发中使用相对路径不是很安全,使用绝对路径又由于不同的电脑中路径不一定相同,所以最好的方式是将相对路径根据系统环境不同、运行方式不同转为绝对路径,或者使用系统中的默认路径(例如图片/视频/文件/下载/用户)。
在Qt中可通过QDir、QFileInfo、QStandardPaths、QCoreApplication、QApplication、qApp来获取不同的路径。
一、Windows下Qt程序使用路径
1.准备工作
-
程序编译后,可执行程序会输出到bin64文件夹下;
- 将可执行程序UsePath.exe创建一个快捷方式到桌面;
- 在桌面创建一个文件夹(桌面文件夹),然后在这个文件夹中创建一个文件(1.xlsx);
- 将【桌面文件夹】创建一个快捷方式到当前路径下。
2.测试结果
-
分别使用Qt编译运行程序、双击可执行程序运行、双击快捷方式、cmd命令行运行四种方式运行UsePath程序;
-
通过对比可以看出前三种运行方式没有什么区别,命令行运行时程序的当前路径为命令行窗口当前路径;
- 所以如果使用命令行启动程序,程序中使用到相对路径的地方就会有问题。
-
如果路径是快捷方式,使用canonicalPath()无法获取路径,会返回空字符串,而使用absolutePath()可以获取快捷方式的绝对路径;
二、Linux下Qt程序使用路径
1.准备工作
-
程序编译后,可执行程序会输出到bin64文件夹下;
- 在桌面创建一个文件夹(桌面文件夹),然后在这个文件夹中创建一个文件(1.xlsx);
- 在bin64文件夹下使用命令
ln -s ~/桌面/桌面文件夹/ ./桌面文件夹-软链接
创建一个软连接到当前路径下; - 在程序中QDir、QFileInfo设置软连接的路径。
2.测试结果
- 由于我测试使用的是ubuntu,程序默认不能双击运行(需要配置桌面xxx.desktop文件才可以,如果是麒麟这些系统支持双击运行),所以就测试编译运行、命令行运行两种方式;
- 命令行启动如下图所示
- 在
用户
路径下使用命令Code/bin64/UsePath
运行程序,程序当前路径(相对路径./
)是用户目录; - 由于【桌面文件夹-软连接】是在
Code/bin64/
目录下,所以在其它路径下使用命令行启动是找不到当前路径下的文件的,这种情况下使用相对路径就会出问题;
- 在
-
Qt编译运行启动如下图所示
- 由Qt编译运行方式启动程序,当前路径(相对路径
./
)是在可执行程序所在路径; - 所以使用相对没有问题,可以找到【桌面文件夹-软连接】;
- 在Linux下使用absolutePath()获取软连接的绝对路径是软连接文件所在路径;
- 在Linux下使用canonicalPath()获取软连接的绝对路径是软连接指向文件的实际所在路径;
- 由Qt编译运行方式启动程序,当前路径(相对路径
三、系统路径
有时候我们需要将文件保存到系统路径下,例如:
- 将截图保存到系统的图片文件夹;
- 将视频文件保存到系统的视频文件夹;
- 将下载的文件保存到系统的下载文件夹;
- 将文件保存到桌面路径;
- 但是Windows、Linux、MacOS的这些文件夹路径都不相同;
- 不同用户的路径也不相同;
- 想要获取这些路径怎么办呢,Qt提供了QStandardPaths类。
四、主要代码
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QDir>
#include <QFileInfo>
#include <QMetaEnum>
#include <QStandardPaths>
#include <QPair>
#include <QList>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowTitle(QString("Qt使用路径的方式和注意使用 V%1").arg(APP_VERSION));
QList<QPair<QString, QString>> paths;
paths << QPair<QString, QString>("QDir::currentPath()", QDir::currentPath()); // 返回应用程序当前目录的绝对路径
paths << QPair<QString, QString>("QDir::homePath()", QDir::homePath()); // 返回用户主目录的绝对路径
paths << QPair<QString, QString>("QDir::rootPath()", QDir::rootPath()); // 返回根目录的绝对路径
// Windows下创建一个文件夹快捷方式或linux下创建一个文件夹链接,将快捷方式路径写入下列QDir
QDir dir("./桌面文件夹 - 快捷方式"); // 指定一个路径
paths << QPair<QString, QString>("QDir::path()", dir.path()); // 返回输入路径,返回的路径可以是绝对路径或相对路径
paths << QPair<QString, QString>("QDir::absolutePath()", dir.absolutePath()); // 返回绝对路径(不区分是不是快捷方式/linux链接 ln)
// 如果是真实路径,效果和absolutePath()相同,如果是windows快捷方式则返回空,如果是linux软硬链接则返回路径地址的实际路径
paths << QPair<QString, QString>("QDir::canonicalPath()", dir.canonicalPath());
paths << QPair<QString, QString>("QCoreApplication::applicationDirPath()", QCoreApplication::applicationDirPath()); // 返回包含应用程序可执行文件的目录
paths << QPair<QString, QString>("qApp->applicationDirPath()", qApp->applicationFilePath()); // 返回应用程序可执行文件的文件路径
// Windows下创建一个文件快捷方式或linux下创建一个文件链接,将快捷方式路径写入下列QDir
QFileInfo info("./桌面文件夹 - 快捷方式/1.xlsx");
// 如果是真实路径,效果和absolutePath()相同,如果是windows快捷方式则返回空,如果是linux软硬链接则返回路径地址的实际路径
paths << QPair<QString, QString>("QFileInfo::canonicalPath()", info.canonicalPath());
paths << QPair<QString, QString>("QFileInfo::canonicalFilePath()", info.canonicalFilePath());
paths << QPair<QString, QString>("QFileInfo::absolutePath()", info.absolutePath()); // 返回输入文件的绝对路径(不包含文件名)
paths << QPair<QString, QString>("QFileInfo::absoluteFilePath()", info.absoluteFilePath()); // 返回输入文件的绝对路径
paths << QPair<QString, QString>("QFileInfo::filePath()", info.filePath()); // 返回文件名,包括路径(可以是绝对路径或相对路径)
paths << QPair<QString, QString>("QFileInfo::path()", info.path()); // 返回文件的路径。这不包括文件名
paths << QPair<QString, QString>("", "--------返回给定位置类型的本地化显示名称--------");
QMetaEnum m = QMetaEnum::fromType<QStandardPaths::StandardLocation>();
for(int i=0; i < m.keyCount(); ++i)
{
QStandardPaths::StandardLocation location = QStandardPaths::StandardLocation(m.value(i));
// 返回给定位置类型的本地化显示名称,如果找不到相关位置,则返回空QString。
paths << QPair<QString, QString>(m.valueToKey(m.value(i)), QStandardPaths::displayName(location));
}
paths << QPair<QString, QString>("", "--------返回类型文件应写入的目录--------");
for(int i=0; i < m.keyCount(); ++i)
{
QStandardPaths::StandardLocation location = QStandardPaths::StandardLocation(m.value(i));
// 返回类型文件应写入的目录,如果无法确定位置,则返回空字符串。
paths << QPair<QString, QString>(m.valueToKey(m.value(i)), QStandardPaths::writableLocation(location));
}
for(int i = 0; i < paths.count(); i++)
{
ui->tableWidget->insertRow(i); //按需求加行
ui->tableWidget->setItem(i, 0, new QTableWidgetItem(paths.at(i).first)); // 插入第一列数据
ui->tableWidget->setItem(i, 1, new QTableWidgetItem(paths.at(i).second)); // 插入第二列数据
}
//自适应宽度
ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
}
Widget::~Widget()
{
delete ui;
}
五、源代码
总结
程序开发中细节决定成败,相对路径、绝对路径不是我们想的那么简单。
整理的路径使用方式和注意事项就到这里,如果有不足欢迎私信我。