IMAN4K IMAN4K - 2 months ago 23
C++ Question

Can not read file with extern type and resource system

I want to read a json file via Qt resource system in a c++ class.

Assume

Translator.h
:

class Translator
{
public:
Translator();

void read(const QString &fpath);
QString valueAt(const QString &key) const;

};

extern Translator _tr;

inline QString Tr(const QSTring &key) {
return _tr.valueAt(key);
}


And
Translator.cpp
:

Translator::Translator() {
read(":/Resources/Text/Translation.json");
}

void Translator::read(const QString &fpath) {
QFile f(fpath);
f.open(QIODevice::ReadOnly | QIODevice::Text);
f.readAll(); // f.errorString() -> no such file or directory
f.close();
}

Translator _tr;


And also
.qrc
file:
.qrc:

<RCC version="1.0">
<qresource>
<file>Resources/Text/Translation.json</file>
</qresource>
</RCC>


Every time i run above code i get error :

QIODevice::read (QFile, ":\Resources\Text\Translation.json"): device not open


However when i remove extern
Translator
object and create that in main function or when replace the path "Resources/Text/Translation.json" with full path there is no more error

Note:



might be good to mention that i want to read
Translator.json
one time in my whole application and for that i create an
extern Translator

Answer

In Cannot open resource file, a first solution can be to run qmake again. It is maybe likely to change the link edition with new dependency information.

Here is a possible explanation. Qt cannot disambiguate ":\Resources\Text\Translation.json" before it reads the content of the .qrc even if the .qrc is compiled in the executable.

So QFile should need (probably during the step of the initialization of the global variables) an initialization to build an internal map (name -> file).

If your initialization of Translator _tr; occurs before this map initialization, you have the error. If it occurs after, things should work.

Another solution could be

class Translator
{
public:
    Translator();

    void read(const QString &fpath);
    QString valueAt(const QString &key) const;
private:
    bool m_ready;
};

Translator::Translator() : m_ready(false) {}

void Translator::read(const QString &fpath) {
    QFile f(fpath);
    f.open(QIODevice::ReadOnly | QIODevice::Text);
    f.readAll(); // f.errorString() -> no such file or directory
    f.close();
}

QString Translator::valueAt(const QString &key) const {
    if (!m_ready) {
      m_ready = true;
      read(":/Resources/Text/Translation.json");
    }
    ...
    return ...;
}