Насколько я понимаю, способ упаковки не кодовых ресурсов, таких как файлы данных, в приложении Qt использует систему ресурсов. Однако, что если я хочу получить доступ к ресурсу, используя функцию не-Qt. Например, у меня может быть файл .txt или .csv с некоторыми данными приложения, к которым я хочу получить доступ, используя ifstream. Кажется, не работает использование синтаксиса «: …» вместо имени файла для не-Qt функций и классов. Существует ли отдельный рабочий процесс для упаковки данных, используемых не-Qt-функциями в приложении?
Я использую OSX, но я бы предположил, что эти проблемы не зависят от платформы.
Единственной целью системы ресурсов 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
вместо этого, поскольку этот класс может быть поддержан чем угодно, не обязательно файлом. Если это код, который вы не контролируете, вы можете настроить 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? Звучит сложно, но не требует слишком много строк кода, смотрите этот ответ.