0

In my class StudentTable I create a function appendRecord as follow-

qint64 StudentTable::appendRecord(Student student){
QFile file(tableName);
QDataStream stream(&file);
qDebug()<<file.open(QIODevice::Append);
qint64 dumpPosition=file.pos();
qDebug()<<file.openMode();

qDebug()<<dumpPosition;
student.next=-1;
student.print();
stream<<student;
file.close();
return dumpPosition;

}

The problem is that when I call the function from main() function directly it works fine. But when I call the same function from the other function in the same class it does nothing; means does not append anything to the file;

Also tried QIODevice::Append, QIODevice::Append|QIODevice::ReadWrite but nothing works for me. I tried because this question : Open QFile for appending says to try something another way; comment of the accepted answer.

I am trying to make a file for students which keeps record of the students. making a record based flat file database; using linked list.

Code: AddRecord() is calling the function appendRecord() in this case nothing happens. But when calling from main() function it appends records in the end.

Add Record Function of StudentTable class...

 bool StudentTable::addRecord(Student student)
    {
        if(isEmpty()&&!isHeapAvailable())
        {
            qDebug()<<"case 1";
            student=Student("rajesh","ramesh",4,5,6);
            qint64 dumpPosition= appendRecord(student);
            Header head=header();
            head.used=dumpPosition;
            head.usedLast=dumpPosition;
            setHeader(head); 
                /*If I comment this setHeader() call here then  
                  appending works else not */

            return true;
        }

        if(!isEmpty()&&!isHeapAvailable())
        {
             qDebug()<<"case 2";
             qint64 dumpPosition= appendRecord(student);
             Header head=header();

             head.usedLast=dumpPosition;
             setHeader(head); /*If I comment this setHeader() call here then  
                  appending works else not */
             return true;
        }

        return false;

    }

I'm using Windows 8, 64bit.

All Files of project:-

Header.h

#ifndef HEADER_H
#define HEADER_H
#include<QtCore>

class Header
{
public:
    qint32 magicNumber;
    qint32 streamVersion;
    qint64 used;
    qint64 usedLast;
    qint64 freeLast;
    qint64 free;
    Header();
    void debug();

};

QDataStream &operator>>(QDataStream &in, Header &painting);
QDataStream &operator<<(QDataStream &out, Header &painting);

#endif // HEADER_H

Header.cpp

#include "header.h"
#include<QtGui>
#include<QtCore>

Header::Header()
{
}

void Header::debug()
{
    qDebug()<<magicNumber<<streamVersion<<used<<free<<usedLast<<freeLast;
}

QDataStream & operator<<(QDataStream &out, Header &header)
{
    out<<header.magicNumber<<header.streamVersion<<header.used<<header.free<<header.usedLast<<header.freeLast;
    return out;
}

QDataStream & operator>>(QDataStream &in, Header &header)
{
    in>>header.magicNumber>>header.streamVersion>>header.used>>header.free>>header.usedLast>>header.freeLast;
    return in;
}

Student.h

#ifndef STUDENT_H
#define STUDENT_H
#include<QtCore>
#include "record.h"

class Student
{
public:

    bool valid;
    static QString fileName;
    quint64 recordLength;
    QString name,fname;
    quint8 age,weight,clss;
    qint64 next;

    Student();
    Student(QString name,QString fname,quint8 age,quint8 weight, quint8 clss);
    void encrypt();
    void print();

};

QDataStream &operator>>(QDataStream &in, Student &painting);
QDataStream &operator<<(QDataStream &out, Student &painting);


#endif // Student_H

Student.cpp

#include "student.h"

Student::Student(QString name, QString fname, quint8 age, quint8 weight, quint8 clss)
{

    Student::fileName="Student";
    recordLength=291;
    this->name=QString(70,' ');
    this->name.replace(0,name.length(),name);

    this->fname=QString(70,' ');
    this->fname.replace(0,fname.length(),fname);

    this->age=age;
    this->weight=weight;
    this->clss=clss;
    this->next=-1;
}

void Student::encrypt()
{

}

Student::Student()
{
    Student::fileName="Student";
    recordLength=291;
    this->name=QString(70,'0');

    this->fname=QString(70,'0');

    this->age=-1;
    this->weight=-1;
    this->clss=-1;
    valid=true;
    this->next=-1;
}

QDataStream & operator<<(QDataStream &out, Student &f)
{

    out<<f.name<<f.fname<<f.age<<f.weight<<f.clss<<f.next;

    return out;


}
QDataStream & operator>>(QDataStream &in, Student &f)
{

    in>>f.name>>f.fname>>f.age>>f.weight>>f.clss>>f.next;

    return in;
}

void Student::print()
{
    qDebug()<<name<<fname<<age<<weight<<clss<<next;
}

QString Student::fileName;

StudentTable.h

#ifndef STUDENTTABLE_H
#define STUDENTTABLE_H
#include "student.h"
#include "header.h"
#include <QtGui>
#include<QtCore>

class StudentTable
{
public:
    StudentTable();
    QString tableName;


    quint64 next;

    void create();
    Header header();
    void setHeader(Header header);
    bool addRecord(Student student);
    QStandardItemModel * getModel();
    qint64 appendRecord(Student student);
    bool isEmpty();
    bool isHeapAvailable();
    void print();
private:


};

StudentTable.cpp

#include "studenttable.h"
#include<QtGui>

#include "header.h"

StudentTable::StudentTable()
{
    tableName="Student";
}

void StudentTable::create()
{
    QFile file(tableName);
    if(file.exists())
        return;
    else
        file.open(QIODevice::Append);
    QDataStream stream(&file);

    Header header;
    header.magicNumber=2015;
    header.streamVersion=stream.version();
    header.used=-1;
    header.free=-1;
    header.usedLast=-1;
    header.freeLast=-1;

    stream<<header;
    file.close();

}

void StudentTable::setHeader(Header header)
{
    QFile file(tableName);
    if(!file.exists())
    {
        qDebug()<<"File "<<tableName<<" doesn't exists";
        return;
    }
    file.open(QIODevice::WriteOnly);
    QDataStream stream(&file);

    stream<<header;

    file.close();
}

Header StudentTable::header()
{
    QFile file(tableName);


    file.open(QIODevice::ReadOnly);
    QDataStream stream(&file);
    Header header;
    stream>>header;

    file.close();
    return header;
}

bool StudentTable::isEmpty()
{
    Header head=header();
    if(head.used==-1)
        return true;
    else return false;
}

bool StudentTable::isHeapAvailable()
{
    Header head=header();
    if(head.free==-1)
        return false;
    else return true;
}

 qint64 StudentTable::appendRecord(Student student)
{
    QFile file(tableName);
    QDataStream stream(&file);
    qDebug()<<file.open(QIODevice::Append);
    qint64 dumpPosition=file.pos();
    qDebug()<<file.openMode();

    qDebug()<<dumpPosition;
    student.next=-1;
    student.print();
    stream<<student;
    file.close();
    return dumpPosition;
}

 void StudentTable::print()
 {
     if(isEmpty())
         qDebug()<<" Table is empty";
     else
     {
         Header head=header();
     QFile file(tableName);
     file.open(QIODevice::ReadOnly);
     QDataStream stream(&file);
     file.seek(head.used);

     Student current;
     stream>>current;
     current.print();
     while(current.next!=-1)
     {
         file.seek(current.next);
         stream>>current;
         current.print();

     }
     file.close();
     }

 }
bool StudentTable::addRecord(Student student)
{
    if(isEmpty()&&!isHeapAvailable())
    {
        qDebug()<<"case 1";
        student=Student("rajesh","ramesh",4,5,6);
        qint64 dumpPosition= appendRecord(student);
        Header head=header();
        head.used=dumpPosition;
        head.usedLast=dumpPosition;
        setHeader(head); 
            /*If I comment this setHeader() call here then  
              appending works else not */

        return true;
    }

    if(!isEmpty()&&!isHeapAvailable())
    {
         qDebug()<<"case 2";
         qint64 dumpPosition= appendRecord(student);
         Header head=header();

         head.usedLast=dumpPosition;
         setHeader(head); /*If I comment this setHeader() call here then  
              appending works else not */
         return true;
    }

    return false;

}

QStandardItemModel * StudentTable::getModel()
{
    QStandardItemModel *model;
    return model;

}

main.cpp

#include "widget.h"
#include <QApplication>
#include "Student.h"
#include "studenttable.h"
#include<QDebug>
#include<QtGui>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    StudentTable studentTable;
    studentTable.create();
    Header header;
    header=studentTable.header();
    header.debug();

    for(int i=1;i<2;i++)
    {
        Student student = Student("ram","bhairu",i,i,i);
        studentTable.addRecord(student);

    }

header=studentTable.header();
header.debug();

//studentTable.print();

    Widget widget;
   // widget.table->setModel(model);
    widget.show();

    return a.exec();
}
Community
  • 1
  • 1
stackOverflow
  • 179
  • 1
  • 2
  • 18
  • Is that [mcve](http://stackoverflow.com/help/mcve) ? – Alexander Stepaniuk Mar 24 '15 at 09:17
  • sorry forget to undo edits; first i tried QIODevice::Append only; and all others in combination with QIODevice::Append; no one worked – stackOverflow Mar 24 '15 at 09:21
  • 2
    `file.open(QIODevice::Append|QIODevice::ReadOnly);` what are you trying to achieve with this? – UmNyobe Mar 24 '15 at 09:22
  • Did you see either `case 1` or `case 2` in output windows of your IDE ? – borisbn Mar 24 '15 at 09:22
  • Tried on both Qt4.3 and Qt 5.3; the same code with some changes; using Windows 8 64bit. – stackOverflow Mar 24 '15 at 09:25
  • 1
    Do not use data stream and iodevice at the same time, it is error prone. Once you create your datastream from your QFile, then do not use the file object. Do not seek, do not look for the position, etc... – UmNyobe Mar 24 '15 at 09:25
  • yes, I see "case 1" and "case 2" both... I used them for debugging... the surprising part is that every time it returns value 40; the file position after opening the file for editing; but does not stream out the record; verified manually opening the file and also rerunning the app; another surprising part is that calling the same function from main() function works well.. – stackOverflow Mar 24 '15 at 09:31
  • @UmNyobe may be.. can u give any link to such document; or tutorial for tips but why it works when called from main function directly; – stackOverflow Mar 24 '15 at 09:37
  • @UmNyobe inline` Do not use data stream and iodevice at the same time, it is error prone. Once you create your datastream from your QFile, then do not use the file object. Do not seek, do not look for the position` **First**, I am not seeking or setting file position after creation of QDataStream object creation just getting file postiong using file.pos() so it should work but not working. **Second** Why it works when called from main() function? **Third** How can I append a file without opening it in Append mode? If any other method exists. – stackOverflow Mar 25 '15 at 10:48
  • You should use: file.open(QIODevice::WriteOnly | QIODevice::Append); everywhere that you open files for writing and want to append to them if they exist. Using just QIODevice::Append isn't sufficient. Also, it's difficult to say what else could be wrong without seeing your Student and Header classes, or at least minimal examples of them. Make sure your file paths are correct; if you're using Qt Creator on Windows, Debug and Release folders share a current working directory space up a directory from the binary. On OS X, relative paths may be created inside the app. – Andrew Dolby Mar 31 '15 at 20:10
  • Could it matter that `appendRecord` opens file after `QDataStream stream(&file);` ? Usually the file open is before but I'm not sure if it matters. – Support Ukraine Apr 01 '15 at 10:45

1 Answers1

-1

Just a confusion because of naming of file opening modes. Problem was in setHeader() function.

void StudentTable::setHeader(Header header)
{
    QFile file(tableName);
    if(!file.exists())
    {
        qDebug()<<"File "<<tableName<<" doesn't exists";
        return;
    }
    file.open(QIODevice::WriteOnly);
    QDataStream stream(&file);

    stream<<header;

    file.close();
}

Every time I have to write file header I open file in QIODevice::WriteOnly mode; that sounds pretty correct because I am neither reading nor seeking file position. But problem is that QIODevice::WriteOnly mode; clear all the data in file and then writes data to file; What I was expecting to just overwrite;

So conclusion is:

If you have to open a file and overwrite some data; use ReadWrite mode instead of QIODevice::WriteOnly mode. QIODevice::WriteOnly will clear all previous data before writing

I don't know why they named it like this. But mode naming is really confusing both in qt and C++. Same thing applies to C++ also.

stackOverflow
  • 179
  • 1
  • 2
  • 18