Как получить доступ к данным ресурса Qt из функций, отличных от Qt

Как я понимаю, способ упаковки некодовых ресурсов, таких как файлы данных в приложении Qt, использует систему ресурсов. Однако, что, если я хочу получить доступ к ресурсу, используя функцию, отличную от Qt. Например, у меня может быть .txt или .csv-файл с некоторыми данными приложения, к которым я хочу получить доступ с помощью ifstream. Кажется, это не работает, чтобы использовать ": ..."синтаксис вместо имени файла для функций и классов, отличных от Qt. Существует ли отдельный рабочий процесс для упаковки данных, используемых не-Qt-функциями в приложение?

Я использую OSX, но я бы предположил, что эти проблемы независимы от платформы.

4 ответов


единственной целью системы ресурсов Qt является объединение данных внутри самого исполняемого файла. Если вы не хотите интегрировать данные в исполняемый файл, вы просто не должны использовать систему ресурсов.

на Mac, Если вы хотите добавить "данные.txt " из источника проекта в ваш пакет приложений, но не в сам исполняемый файл, добавьте следующее в свой :

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;
}

в приведенном выше примере и ничего С системой ресурсов Qt. Это просто соглашение об именах в пакетах приложений OS X. Мы не используем систему ресурсов Qt здесь.

если вы хотите использовать систему ресурсов Qt и получить доступ к данным ресурсов напрямую, а не через QFile, the QResource класс предоставляет доступ к ресурсам, которые входят в комплект выполнимый.

если код под вашим контролем настаивает на использовании ifstream для ввода данных, то он искусственно ограничен и должен быть исправлен. Он должен использовать istream вместо этого, поскольку этот класс может быть подкреплен чем угодно, не обязательно файлом. Если это код, который вы не контролируете, вы можете настроить ifstream на QLocalSocket.

вы можете назначить постоянный QResource::data() к входному потоку через буфер потока.

если ресурс isCompressed(), тогда вам нужно сначала распаковать его во временную область. Вы также можете отключить сжатие ресурсов чтобы избежать кессонной шаг. Вы можете использовать полностью исполняемый компрессор, как UPX по вместо этого-к моменту запуска вашего кода все будет уже распаковано и готово к использованию.


вы можете скопировать файл ресурсов во временную папку. Для этого используйте 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

Qt производит большие qrc_*.cpp файлы, которые компилируются в исполняемый файл, если вы объявите их в своем .pro файл, как RESOURCES = myResources.qrc. Поэтому в этом случае вы можете получить к ним доступ только в своем приложении Qt.

однако, если вы можете повлиять на код загрузки ресурсов, вы не можете компилировать ресурсы, но явно загружать их во время выполнения с помощью

QResource::registerResource("/path/to/myResources.rcc")

и радостно читать их с диска, как обычные файлы.


Как насчет открытия файла ресурсов с помощью объекта QFile, обертывания его с помощью объекта QDataStream и обертывания его с помощью объекта boost::iostreams::stream, который происходит от специализации std::basic_istream? Звучит сложно, но не требует слишком много строк кода, см. ответ.