如何从非Qt函数访问Qt资源数据

时间:2014-10-20 21:00:42

标签: c++ qt packaging

据我了解,在Qt应用程序中打包非代码资源(如数据文件)的方法是使用资源系统。但是,如果我想使用非Qt函数访问资源该怎么办?例如,我可能有一个.txt或.csv文件,其中包含一些我想使用ifstream访问的应用程序数据。似乎不能使用“:...”语法代替非Qt函数和类的文件名。是否有单独的工作流程来打包应用程序中非Qt函数使用的数据?

我正在使用OSX,但我认为这些问题与平台无关。

4 个答案:

答案 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