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("foo/foo.ino"); fooTemplate = new QFile(":/data/template.ino"); for(int i=0; i<m_moduleCount; i++) { QFile *file = new QFile("foo/module"+QString::number(i)+".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!
-
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
-
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.