以 QIODevice::Append 模式打开的 QFile 意外工作。这是一个Qt错误吗?
QFile opened in QIODevice::Append mode working unexpectedly. Is it a Qt bug?
在我的 class StudentTable 中,我创建了一个函数 appendRecord,如下所示-
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;
}
问题是,当我直接从 main() 函数调用函数时,它工作正常。但是当我从同一个 class 中的另一个函数调用同一个函数时,它什么也不做;表示不向文件附加任何内容;
也尝试了 QIODevice::Append、QIODevice::Append|QIODevice::ReadWrite,但对我没有任何作用。我试过是因为 this question : Open QFile for appending 说要尝试另一种方法;已接受答案的评论。
我正在尝试为学生制作一个文件来记录学生。制作基于记录的平面文件数据库;使用链表。
代码:AddRecord() 正在调用函数 appendRecord() 在这种情况下没有任何反应。但是当从 main() 函数调用时,它会在最后附加记录。
增加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;
}
我正在使用 Windows 8、64 位。
项目的所有文件:-
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();
}
只是文件打开模式的命名造成了混淆。问题出在 setHeader()
函数中。
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();
}
每次我必须写文件头时,我都会以 QIODevice::WriteOnly
模式打开文件;这听起来很正确,因为我既不阅读也不寻找文件位置。但问题是 QIODevice::WriteOnly
模式;清除文件中的所有数据,然后将数据写入文件;我期望覆盖的内容;
所以结论是:
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
我不知道他们为什么这样命名。但是模式命名在 qt 和 C++ 中确实令人困惑。同样的事情也适用于 C++。
在我的 class StudentTable 中,我创建了一个函数 appendRecord,如下所示-
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;
}
问题是,当我直接从 main() 函数调用函数时,它工作正常。但是当我从同一个 class 中的另一个函数调用同一个函数时,它什么也不做;表示不向文件附加任何内容;
也尝试了 QIODevice::Append、QIODevice::Append|QIODevice::ReadWrite,但对我没有任何作用。我试过是因为 this question : Open QFile for appending 说要尝试另一种方法;已接受答案的评论。
我正在尝试为学生制作一个文件来记录学生。制作基于记录的平面文件数据库;使用链表。
代码:AddRecord() 正在调用函数 appendRecord() 在这种情况下没有任何反应。但是当从 main() 函数调用时,它会在最后附加记录。
增加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;
}
我正在使用 Windows 8、64 位。
项目的所有文件:-
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();
}
只是文件打开模式的命名造成了混淆。问题出在 setHeader()
函数中。
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();
}
每次我必须写文件头时,我都会以 QIODevice::WriteOnly
模式打开文件;这听起来很正确,因为我既不阅读也不寻找文件位置。但问题是 QIODevice::WriteOnly
模式;清除文件中的所有数据,然后将数据写入文件;我期望覆盖的内容;
所以结论是:
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
我不知道他们为什么这样命名。但是模式命名在 qt 和 C++ 中确实令人困惑。同样的事情也适用于 C++。