1

I have an assignment where I am writing input on various things (in the form of structs) and then writing to a binary file. I have to be able to both read and write to the file while the program is open. One of the methods needs to print out all of the clients in the binary file. It seems to be working, except whenever I call that method, it seems to erase the contents of the file and prevent more from being written to it. Here's the applicable snippets:

fstream binaryFile;
binaryFile.open("HomeBuyer", ios::in | ios::app | ios::binary);

The same file is supposed to be usable between times you run the program, so I should open it with ios::app, correct?

Here's the method to add an entry:

void addClient(fstream &binaryFile) {
      HomeBuyer newClient; //Struct the data is stored in
      // -- Snip -- Just some input statements to get the client details //

      binaryFile.seekp(0L, ios::end); //This should sent the write position to the
                                     //end of the file, correct?
      binaryFile.write(reinterpret_cast<char *>(&newClient), sizeof(newClient));

      cout << "The records have been saved." << endl << endl;
}

And now the method to print all the entries:

void displayAllClients(fstream &binaryFile) {
    HomeBuyer printAll;
    binaryFile.seekg(0L, ios::beg);
    binaryFile.read(reinterpret_cast<char *>(&printAll),sizeof(printAll));

    while(!binaryFile.eof()) {  //Print all the entries while not at end of file
        if(!printAll.deleted)  {
             // -- Snip -- Just some code to output, this works fine //
        }

        //Read the next entry
        binaryFile.read(reinterpret_cast<char *>(&printAll),sizeof(printAll)); 
    }
    cout << "That's all of them!" << endl << endl;
}

If I step through the program, I can input as many clients as I want, and it will output them all the first time I call displayAllClients(). But as soon as I call displayAllClients() once, it seems to clear out the binary file, and any further attempts at displaying clients gives me no results.

Am I using seekp and seekg incorrectly?

From what I understand, this should set my write position to the end of the file:

binaryFile.seekp(0L, ios::end);

And this should set my read position to the beginning:

binaryFile.seekg(0L, ios::beg);

Thanks!

Mat
  • 202,337
  • 40
  • 393
  • 406
Nate
  • 925
  • 2
  • 12
  • 23
  • Check that the writes are successful, I am unsure if `ios::out` is implicitly specified when `ios::app` is. – hmjd Apr 27 '12 at 21:36
  • The writes seem to be successful, but I tried it with ios::out just to check, and it seems to be doing the same thing. That is, the writes seem to be successful until I call a method other than the addClient() method. – Nate Apr 27 '12 at 21:40
  • 2
    I think you also need to call `binaryFile.clear()` before `seekp()` and `seekg()` if EOF is set, otherwise they won't work. – hmjd Apr 27 '12 at 21:41
  • What does your `HomeBuyer` class look like? What data members does it have? You are assuming that its native byte format is usable as a serialized instance, but this is not guaranteed. – David Schwartz Apr 27 '12 at 21:45
  • @David Schwartz: sorry, I should have clarified. HomeBuyer is just a struct with 3 C-strings, two doubles, and a bool. – Nate Apr 27 '12 at 21:47
  • @hmjd: Adding binaryFile.clear() worked! Thanks a ton! Feel free to add it as an answer so I can accept it. – Nate Apr 27 '12 at 21:47
  • 1
    @Nate: Then it will likely work, but I still think this is a bad idea. If you need a class serialized, IMO, you should serialize it. – David Schwartz Apr 27 '12 at 21:55

2 Answers2

3

Pasting comment in as this resolved the issue.

You need to call binaryFile.clear() before seekp() and seekg() if EOF is set, otherwise they won't work.

hmjd
  • 120,187
  • 20
  • 207
  • 252
  • Thanks, this seems to have done it. I'm still having problems elsewhere, but I think it may be related to smockings answer. Thanks! – Nate Apr 27 '12 at 21:50
1

This is the documentation for ios::app

ios::app

    All output operations are performed at the end of the file, appending the
    content to the current content of the file. This flag can only be used in 
    streams open for output-only operations.

Since this is homework, I'll let you draw your own conclusions.

smocking
  • 3,689
  • 18
  • 22