954,506 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Writing to binary file, erases previous data?

I'm doing a homework for my programming class, the following code is a part of my code which I cut out and formatted to be a 'runnable' program.
Now, if you run it you'll notice it creates a data.txt file, writing the amount of student IDs in the record as the first 4 bytes, and then it writes the student number (9 bytes) starting at byte 20 (the reason it starts at byte 20 is because the other unused 16 bytes are used for other data in my program... functions which I still have not coded. Each student will use up 244 bytes.

Now here is the problem: If you run the program again, the second studentID will be saved at the appropriate bytes but the previous ID is erased!

Hope someone can help me with this, thanks ;).

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#define tCLASSES 10

using namespace std;
int numRecords=0;
int classes;
int grades = 0;
int offset;

void checkRecords();
void writeNumber(std::string&);

int main(){
    string buff;
    
    againNum:
    // STUDENT NUMBER--------------------------------------------------
    cout << "Type the student's number : ";
    getline(cin, buff);
    if (buff.length()!=9){
       //system("cls");
       cout << "*** ID Number must be 9 characters long\n";
       goto againNum;
    }
    //STORE IN BIN FILE
    writeNumber(buff);
}


void writeNumber(string& buff){
     checkRecords();
     cout << "Offset = 4 + (" << numRecords << " * (44 + (" << tCLASSES << " * 24)))\n";
     offset = 4 + (numRecords * (44 + (tCLASSES*24)));
     cout << "Offset is " << offset << ".\n";
     ofstream semData("data.txt", ios::binary);
     semData.seekp(offset+16);
     cout << "Writing student number to bin file at " << semData.tellp() << "!\n";
     semData.write((buff.c_str()), 9);
     system("PAUSE");
     numRecords++;
     semData.seekp(0);
     cout << "Writing # of records (" << numRecords << ") to bin file at " << semData.tellp() << "!\n";
     semData.write(reinterpret_cast<char*>(&numRecords),4);
     semData.close();

}

void checkRecords()
{
     ifstream semData("data.txt", ios::binary);
     if (!semData.is_open())
     {
        semData.close();
        ofstream semData("data.txt", ios::binary);
        semData.close();
     }
     else
     {
         ifstream semData("data.txt", ios::binary);
         semData.read(reinterpret_cast<char*>(&numRecords), 4);
         cout << "There are " << numRecords << " students in the record.\n";
         semData.close();
     }
}
fesago90
Newbie Poster
21 posts since Jan 2007
Reputation Points: 10
Solved Threads: 1
 

I guess thats because when you open your file the next time, you don't use the iostream flag append and thats the reason your previous contents get erased.

A file which already has contents when opened for writing needs to be opned in append mode for preserving the previous contents. More information and example here.

~s.o.s~
Failure as a human
Administrator
11,938 posts since Jun 2006
Reputation Points: 3,281
Solved Threads: 734
 

I guess thats because when you open your file the next time, you don't use the iostream flag append and thats the reason your previous contents get erased.

A file which already has contents when opened for writing needs to be opned in append mode for preserving the previous contents. More information and example here.

Yeah, I just noticed that I wasn't using the app flag. Now, changing

ofstream semData("data.txt", ios::binary);

to

fstream semData("data.txt", ios::out|ios::binary|ios::app);


makes things even worst. Data isn't written to the appropriate addresses.

What else am I supposed to add?
It would seem that the ios::nocreate flag is the one I need but it doesn't seem to be included in the standard libary... and I know there should be a way of doing these without the need of non-standard libraries.

Hopefully you or someone else will notice something else missing!

Thanks!

fesago90
Newbie Poster
21 posts since Jan 2007
Reputation Points: 10
Solved Threads: 1
 

hmm I was expectin ios::ate to work instead of the append flag... but it didn't.

I added the ios::in flag to do some debugging while in the program and I noticed that it worked.

In other words, seems I needed the ios::in flag too... hmm it makes sense.

fesago90
Newbie Poster
21 posts since Jan 2007
Reputation Points: 10
Solved Threads: 1
 

It would be easier to read youe header record, then read the number of students specified into a student array. After you add a new student to the array, recreate the file by outputting the header and all the students.

WaltP
Posting Sage w/ dash of thyme
Moderator
10,506 posts since May 2006
Reputation Points: 3,348
Solved Threads: 944
 

that might be easier to program, but it's not a desirable solution.
If the file gets larger it will inevitably be a LOT slower than modifying the existing file.
It could also easily lead to out of memory errors.

jwenting
duckman
Team Colleague
8,392 posts since Nov 2004
Reputation Points: 1,662
Solved Threads: 337
 
that might be easier to program, but it's not a desirable solution. If the file gets larger it will inevitably be a LOT slower than modifying the existing file. It could also easily lead to out of memory errors.


I see your point -- in a professional setting. ButI'm doing a homework for my programming class, ... tells me your apprehension is unfounded and the OPmay be using a technique beyond him at this time. I may be wrong, but it's worth pointing out.

WaltP
Posting Sage w/ dash of thyme
Moderator
10,506 posts since May 2006
Reputation Points: 3,348
Solved Threads: 944
 

void checkRecords()
{
ifstream semData("data.txt", ios::binary);
if (!semData.is_open())
{
semData.close();
ofstream semData("data.txt", ios::binary);
semData.close();
}
else
{
ifstream semData("data.txt", ios::binary);
semData.read(reinterpret_cast(&numRecords), 4);
cout << "There are " << numRecords << " students in the record.\n";
semData.close();
}
}

I don't claim to be an expert but logically what if he opens up a file and it opened successfully, why does he open up the same file again? And if intentional where does he close it?

Lazaro Claiborn
Junior Poster
171 posts since Jan 2007
Reputation Points: 11
Solved Threads: 13
 

It wasn't intentional ;) , although it didn't cause any errors.
Thanks for pointing that out :) .

fesago90
Newbie Poster
21 posts since Jan 2007
Reputation Points: 10
Solved Threads: 1
 
I see your point -- in a professional setting. But tells me your apprehension is unfounded and the OP may be using a technique beyond him at this time. I may be wrong, but it's worth pointing out.

IMO you should start people by teaching them the right way to do things, rather than teaching them a quick hack now and later trying to explain that they were taught to do things incorrectly because the right way takes a few more lines of code.

jwenting
duckman
Team Colleague
8,392 posts since Nov 2004
Reputation Points: 1,662
Solved Threads: 337
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You