据我了解,在Qt应用程序中打包非代码资源(如数据文件)的方法是使用资源系统。但是,如果我想使用非Qt函数访问资源该怎么办?例如,我可能有一个.txt或.csv文件,其中包含一些我想使用ifstream访问的应用程序数据。似乎不能使用“:...”语法代替非Qt函数和类的文件名。是否有单独的工作流程来打包应用程序中非Qt函数使用的数据?
我正在使用OSX,但我认为这些问题与平台无关。
答案 0 :(得分:4)
Qt资源系统的唯一目的是将数据捆绑在可执行文件本身中。如果您不希望将数据集成到可执行文件中,那么您就不能使用资源系统。
在Mac上,如果您希望将“data.txt”从项目源添加到应用程序包中,而不是添加到可执行文件本身,请将以下内容添加到.pro
文件中:
mac {
BUNDLE = $$OUT_PWD/$$TARGET$$quote(.app)/Contents
QMAKE_POST_LINK += ditto \"$$PWD/data.txt\" \"$$BUNDLE/Resources/\";
}
鉴于上述项目文件,请使用QCoreApplication::applicationDirPath()
获取有助于获取文件的路径:
#include <QCoreApplication>
#include <QFile>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << QCoreApplication::applicationDirPath();
QFile data(QCoreApplication::applicationDirPath() + "/../Resources/data.txt");
if (data.open(QIODevice::ReadOnly | QIODevice::Text))
qDebug() << data.readAll();
return 0;
}
在上面的示例中,Resources
文件夹与Qt资源系统无关。它只是OS X应用程序包中的命名约定。我们这里没有使用Qt资源系统。
如果您希望使用Qt资源系统并直接访问资源数据而不是QFile
,则QResource
类可以访问可执行文件中捆绑的资源。
如果您控制下的代码坚持使用ifstream
进行数据输入,那么它是人为限制的,应该修复。它应该使用istream
,因为该类可以由任何东西支持,不一定是文件。如果是您无法控制的代码,则可以在QLocalSocket
上设置ifstream
。
您可以通过流缓冲区映射常量QResource::data()
to an input stream。
如果资源isCompressed()
,则需要先将其解压缩到临时区域。您还可以disable resource compression避免解压缩步骤。您可以使用整个可执行的压缩器,例如upx - 在代码运行时,所有内容都已经解压缩并可以使用。
答案 1 :(得分:2)
您可以将资源文件复制到临时文件夹中。要执行此操作,请使用QTemporaryDir
创建临时文件夹,并在程序完成时自动将其删除。要访问该文件夹的路径,请使用QTemporaryDir::path()
方法。以下是如何使用它的示例:
#include <QTemporaryDir> //You need to include this header
QTemporaryDir temporaryDir;
//Copy the resource file into the temporary folder
QFile::copy(":/exampleprefix/examplefile.txt", temporaryDir.path() + "/examplefile.txt");
//Read the file
std::ifstream fileStream(QString(temporaryDir.path() + "/examplefile.txt").toLatin1().data());
//etc
答案 2 :(得分:1)
Qt会生成大型qrc_*.cpp
文件,如果您在.pro文件中声明它们,就会编译成可执行文件,如RESOURCES = myResources.qrc
。因此,在这种情况下,您只能在Qt应用程序中访问它们。
但是,如果您可以影响资源加载代码,则可能无法编译资源,而是在运行时使用
显式加载它们QResource::registerResource("/path/to/myResources.rcc")
并愉快地从常规文件中读取它们。
答案 3 :(得分:0)
如何用QFile对象打开资源文件,用QDataStream对象包装它,并用boost :: iostreams :: stream对象包装它,它来自std :: basic_istream的特化?听起来很复杂,但不需要太多代码,请参阅this answer。