1

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

Community
  • 1
  • 1
IMAN4K
  • 1,265
  • 3
  • 24
  • 42
  • 1
    It could be an ordering problem in the initialization of the global variables. A solution could be to initialize `_tr` after all other global variables. ex: declaring it with `Translator* _tr = nullptr;` and calling `_tr = new Translator` at the beginning of `main` or in the first function that uses it. – Franck Sep 29 '16 at 16:32
  • @Frank.Could you please take another look at my Translator.h.actually i want in every source file that we include Translator.h we will be able to use Tr() function and initializing in main or initializing in every source file is not possible for my case – IMAN4K Sep 29 '16 at 16:51
  • You can for example define `Tr(...)` with `if (!_tr) _tr = new Tranlator; return _tr->valueAt...`. It is just a first proposal to isolate the problem. – Franck Sep 29 '16 at 16:56
  • @frank.there is also one more thing if i declare the file (in constructor) as full path like ""C:/Users//Documents/Resources/Text/Translation.json" there is no more error.you have any idea why this happen ? – IMAN4K Sep 29 '16 at 17:05
  • I don't know about `QIODevice` but maybe it uses resources defined in the global variable initialization step to find the full path from a relative path. I google that. – Franck Sep 29 '16 at 17:09

1 Answers1

1

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 ...;
}
Community
  • 1
  • 1
Franck
  • 1,635
  • 1
  • 8
  • 11