Open text file from ressources multiple times



  • Hey everyone!

    I just wrote a small code generator for a recent project, that generates Arduino code from a Template for certain hardware configurations. The function works fine, if I call it for the first time. Any further call during execution results in an empty template file, which is a simple text file in the ressources whitch does not change at all.

    Here is the code:
    Constructor:
    @CodeMerger::CodeMerger(QObject *parent, int moduleCount) : QObject(parent)
    {
    m_moduleCount = moduleCount;

    moduleFiles = new QList<QFile*>;
    QDir().mkdir("foo");
    m_fooFile = new QFile&#40;"foo/foo.ino"&#41;;
    fooTemplate = new QFile(":/data/template.ino"&#41;;
    
    for(int i=0; i<m_moduleCount; i++&#41;
    {
        QFile *file = new QFile&#40;"foo/module"+QString::number(i&#41;+".h");
        file->open(QFile::ReadWrite | QFile::Truncate);
        moduleFiles->append(file);
        file->close();
    }
    

    }
    @
    Generator:
    @bool CodeMerger::merge(QList<fooModule *> configList)
    {
    // valid config list?
    if(configList.size() != m_moduleCount)
    {
    m_errorMsg = tr("Invalid module config list.");
    return false;
    }

    if(!fooTemplate->open(QFile::ReadOnly | QFile::Text) || !fooTemplate->size())
    {
        m_errorMsg = tr("Template error");
        qDebug() << fooTemplate->size();
    
       // !! HERE IS THE ERROR:
       // every further call of this function reaults in fooTemplate->size() beeing 0, but I don't change the source file anywhere!
    
        fooTemplate->close();
        return false;
    }
    if(!m_fooFile->open(QFile::ReadWrite | QFile::Text | QFile::Truncate))
    {
        m_errorMsg = tr("foo master file error.");
        fooTemplate->close();
        return false;
    }
    
    // copy template to master file
    QByteArray masterBuffer(fooTemplate->readAll());
    fooTemplate->close();
    
    // module file content creation loop
    for(int i=0; i<m_moduleCount; i++)
    {
        QFile *file = moduleFiles->at(i);
    
        if(!file->open(QFile::ReadWrite | QFile::Text | QFile::Truncate))
        {
            m_errorMsg = file->errorString();
            m_fooFile->close();
            return false;
        }
    
        if(configList.at(i))
        {
            // create module file content
            QByteArray moduleCodeBuffer;
            moduleCodeBuffer.append(configList.at(i)->code());
            moduleCodeBuffer.replace("write(", "::foo.write("+QString::number(i).toLocal8Bit()+", ");
    
            // write module code file
            if(file->write(moduleCodeBuffer) == -1)
            {
                m_errorMsg = file->errorString();
                file->close();
                m_fooFile->close();
                return false;
            }
    
            // enable module in master file
            int posS = masterBuffer.indexOf("//connector"+QString::number(i)+"::setup();");
            masterBuffer.remove(posS, 2);
            int posL = masterBuffer.indexOf("//connector"+QString::number(i)+"::loop();");
            masterBuffer.remove(posL, 2);
        }
    
        file->close();
    }
    
    if(m_fooFile->write(masterBuffer) == -1)
    {
        m_errorMsg = m_fooFile->errorString();
        m_fooFile->close();
        return false;
    }
    
    m_fooFile->close();
    
    return true;
    

    }
    @

    Has anybody an idea what might be wrong?

    Thank you very much!


  • Lifetime Qt Champion

    Hi,

    It's a surprising behavior. However since you are reusing the same template again and again, you could read it in a QByteArray and reuse it or just call seek(0) rather than re-open the file each time.

    Hope it helps


  • Moderators

    Keeping the template in memory (QByteArray) like SGaist said would be faster and solve the problem.

    Along the lines of the actual problem though, I notice that QFile has some weird behavior to it if you try to reuse them.

    You can try doing fooTemplate->reset() before you use it again, or better yet I prefer just to create the QFile as I need it. There is no reason to "new" it in your constructor and then continually try to close/reopen it. It is just as easy to do:

    @
    QFile fooTemplate("myfile");
    if (!fooTemplate.open(...))
    xxx;

    // as it is to do:

    Cons::Cons()
    {
    fooTemplate = new QFile("myfile");
    }

    Cons::MyFunc()
    {
    if (!fooTemplate->open(...))
    xxx;
    }
    @

    Doing the former will always have a working file and you don't have to worry about the idiosyncrasy of QFile.

    The best solution is definitely to save it in a buffer and only read it once though. It will be faster (RAM vs Disk access) and solve the problem as well.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.