Reputation: 13
Hi, guy I was trying to build a Qt Gui application that lets the user inputs all data and write it into file using c++ file stream. And when I try to read all the data back from file it work fine for the first time, but when I close the application and try to read it again my application got crush. I try to fix it the best I can, but I couldn't find any solution. Could anyone help help me. Here my source code for reading data from file.
void Form::OpenSlot()
{
OpenDialog = new QFileDialog();
FilePath = OpenDialog->getOpenFileName(this,"Open",AppDir,"Binary Files(*.bin)");
QString strID, strName, strSex, strSalary, strHour, strRate, strTotal;
int row = 0;
Employee *emp = NULL;
if(!FilePath.isEmpty())
{
isNew = false;
fstream fout(FilePath.toStdString().c_str(),ios::binary|ios::in);
if(fout.fail())
{
msg->setText("Error reading file.\nWrong format.");
msg->show();
fout.close();
return;
}
fout.seekg(0,ios::end);
row = (int)(fout.tellg()/sizeof(Employee));
fout.seekg(0,ios::beg);
emp = new Employee[row];
fout.read((char*)emp,row*sizeof(Employee));
fout.close();
for(int i=0;i<row;i++)
{
DisplayTable->removeRow(i);
}
for(int i=0;i<row;i++)
{
strID = QString::number((emp+i)->getID());
strName = QString::fromStdString((emp+i)->getName());
strSex = QString::fromStdString((emp+i)->getSex());
strSalary = QString::number((emp+i)->getSalary());
strHour = QString::number((emp+i)->getHour());
strRate = QString::number((emp+i)->getRate());
strTotal = QString::number((emp+i)->getTotal());
DisplayTable->insertRow(i);
DisplayTable->setItem(i,0,new QTableWidgetItem(strID));
DisplayTable->setItem(i,1,new QTableWidgetItem(strName));
DisplayTable->setItem(i,2,new QTableWidgetItem(strSex));
DisplayTable->setItem(i,3,new QTableWidgetItem(strSalary));
DisplayTable->setItem(i,4,new QTableWidgetItem(strHour));
DisplayTable->setItem(i,5,new QTableWidgetItem(strRate));
DisplayTable->setItem(i,6,new QTableWidgetItem(strTotal));
}
}
else
{
msg->setText("Can not find path");
msg->show();
}
delete []emp;
}
And here is the source code for writting data into file.
void Form::SaveSlot()
{
int row = DisplayTable->rowCount();
// Write Data to file
if(!isNew)
{
fstream fin(FilePath.toStdString().c_str(),ios::binary|ios::out);
Employee *emp = new Employee[row];
for(int i=0;i<row;i++)
{
emp->setID(DisplayTable->item(i,0)->text().toInt());
emp->setName(DisplayTable->item(i,1)->text().toStdString());
emp->setSex(DisplayTable->item(i,2)->text().toStdString());
emp->setSalary(DisplayTable->item(i,3)->text().toFloat());
emp->setHour(DisplayTable->item(i,4)->text().toInt());
emp->setRate(DisplayTable->item(i,5)->text().toFloat());
emp->setTotal(DisplayTable->item(i,6)->text().toFloat());
fin.write((char*)&emp,sizeof(Employee));
}
fin.close();
}
else
{
SaveDialog = new QFileDialog();
FilePath = SaveDialog->getSaveFileName(this,"Save",AppDir,"BinaryFile(*.bin)");
if(FilePath.isEmpty())
return;
fstream fin(FilePath.toStdString().c_str(),ios::binary|ios::out);
Employee *emp = new Employee[row];
for(int i=0;i<row;i++)
{
(emp+i)->setID(DisplayTable->item(i,0)->text().toInt());
(emp+i)->setName(DisplayTable->item(i,1)->text().toStdString());
(emp+i)->setSex(DisplayTable->item(i,2)->text().toStdString());
(emp+i)->setSalary(DisplayTable->item(i,3)->text().toFloat());
(emp+i)->setHour(DisplayTable->item(i,4)->text().toInt());
(emp+i)->setRate(DisplayTable->item(i,5)->text().toFloat());
(emp+i)->setTotal(DisplayTable->item(i,6)->text().toFloat());
}
fin.write((char*)emp,row*sizeof(Employee));
fin.close();
}
}
And here is the Employee class prototype.
class Employee
{
public:
Employee();
Employee(Employee &emp);
Employee(int id,string name,string sex,float salary,int hour,float rate,float total);
void setID(int id);
void setName(string name);
void setSex(string sex);
void setSalary(float salary);
void setHour(int hour);
void setRate(float rate);
void setTotal(float total);
int getID();
string getName();
string getSex();
float getSalary();
int getHour();
float getRate();
float getTotal();
private:
int m_id;
string m_name;
string m_sex;
float m_salary;
int m_hour;
float m_rate;
float m_total;
};
Upvotes: 0
Views: 1262
Reputation: 8293
One possible issue:
fstream fout(FilePath.toStdString().c_str(),ios::binary|ios::in);
Here FilePath.toStdString()
returns a temporary std::string
, then you call c_str()
and get a pointer to its data. Then the temporary string is destroyed, and you send the dangling pointer to the fstream constructor! You could do this:
string filePathStr = FilePath.toStdString();
fstream fout(filePathStr.c_str(),ios::binary|ios::in);
Or use QFile
directly. It takes a QString
for file path.
Also, you are not deleting emp
on void Form::SaveSlot()
:
Employee *emp = new Employee[row];
(does not cause your crash, but is a memory leak you probably want to avoid.)
Upvotes: 1