-4

Possible Duplicate:
Reading from text file until EOF repeats last line

I am writting data to a file using the following code

//temp is class object
fstream f;
f.open ("file", ios::in|ios::out|ios::binary);
for(i=0;i<number_of_employees ;++i)
{
temp.getdata();
f.write( (char*)&temp,sizeof(temp));
}
f.close();

temp is the object of following class

class employee
 {
 char eno[20];
 char ename[20];
 char desg[20];
 int bpay;
 int ded;
 public:
 void getdata();
 void displaydata();
}

But when i write data using this code i find that the last object written to file gets written two times.

my function to read from file is

fstream f;
f.open ("file", ios::in|ios::out|ios::binary);
while(f)
{
f.read((char*)&temp, sizeof(temp));
temp.displaydata();
}
f.close();

following shows my file when it is read till eof

Number       :1
Name       :seb
Designation:ceo
Basic Pay  :1000
Deductions :100

Number       :2
Name       :sanoj
Designation:cto
Basic Pay  :2000
Deductions :400

Number       :2
Name       :sanoj
Designation:cto
Basic Pay  :2000
Deductions :400

What is the cause of this and how can i solve it?

Community
  • 1
  • 1

3 Answers3

2

If the problem is repeated output, it's very likely caused by the way you are looping. Please post the exact loop code.

If the loop is based on the data you receive from getdata(), you'll need to look closely at exactly what you input as well. You might not be receiving what you expect.

Of course, without real code, these are almost just guesses.

1

The reason for your problem is simple: you're not checking whether the read has succeeded before using the results. The last read encounters end of file, fails without changing the values in your variables, and then you display the old values. The correct way to do exactly what you're trying to do would be:

while ( f.read( reinterpret_cast<char*>( &temp ), sizeof( temp ) ) ) {
    temp.displaydata();
}

Exactly what you're trying to do, however, is very fragile, and could easily break with the next release of the compiler. The fact that your code needs a reinterpret_cast should be a red flag, indicating that what you're doing is extremely unportable and implementation dependent. What you need to do is first, define a binary format (or use one that's already defined, like XDR), then format your data according to it into a char buffer (I'd use std::vector<char> for this), and finally use f.write on this buffer. On reading, it's the reverse: you read a block of char into a buffer, and then extract the data from it. std::ostream::write and std::istream::read are not for writing and reading raw data (which makes no sense anyway); if they were, they'd take void*. They're for writing and reading pre-formatted data.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
0

Writing an object to a file with write((char*)object, sizeof(object)) is looking for trouble!

Rather write a dedicated write function for the class:

class employee {
  ...
  void write(ostream &out) {
    out.write(eno, sizeof(eno));
    out.write(ename, sizeof(ename));
    out.write(desg, sizeof(desg));
    out.write((char*)&bpay, sizeof(bpay));
    out.write((char*)&ded, sizeof(ded));
  }
  void read(istream &in) {
    in.read(&eno, sizeof(eno));
    in.read(&ename, sizeof(ename));
    ...
    in.read((char*)&bpay, sizeof(bpay));
    in.read((char*)&ded, sizeof(ded));
  }

}

ostream &operator <<(ostream &out, employee &e) {
  e.write(out);
  return out;
}
istream &operator >>(istream &in, employee &e) {
  e.read(in);
  return in;
}

Once you've done that, you can use:

f << temp;

to write your employee record to the file.

But note that even this isn't great, because at least as far as the integers are concerned, we're becoming very platform dependent, ito the size of an int, and ito the endianness of the int.

craigmj
  • 4,827
  • 2
  • 18
  • 22