We're a community of 1.1M IT Pros here for help, advice, solutions, professional growth and fun. Join us!
1,080,650 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Start New Discussion Reply to this Discussion

Binary File I/O Problem

In my program I am creating a class instance then writing it to a binary file. I do this several times so I have several instances of this class in my file. Then I want to access them individually, read them back into an instance in the program, change its contents and write it back into its place in the file.

I have most of it working fine, however there's one problem. When I edit the contents of the class and try to write it back to the file in its correct spot by using seekp(offset) where offset is basically an index number of the record I'm interacting with, it writes it in the correct spot but it's deleting every record before and after it. So say if I've read in the 5th record in the file, changed its contents and write it back after using seekp(offset*sizeof(A)) it writes it back in at the desired location but before it is filled with null data and after it there is nothing (end of file). I tried fiddling with the ios flags to make sure it wasn't truncating it, using reinterpret_cast<char*> instead of (char*), and I just can't figure out what's wrong.

Here's the simplified code:

class A {
private:
    char array[10];
public:
    void writeToFile(int);
    void readFromFile(int);
};

void A::writeToFile(int offset)
{
    ofstream outFile("data.bin", ios::out | ios::binary);
    outFile.seekp(offset*sizeof(A));
    outFile.write((char*)this, sizeof(A));
    outFile.close();
}

// readFromFile is the same except ifstream, ios::in, seekg and read are used.

Any help would be appreciated!

3
Contributors
7
Replies
20 Hours
Discussion Span
3 Years Ago
Last Updated
8
Views
Question
Answered
Reprise
Newbie Poster
20 posts since May 2009
Reputation Points: 10
Solved Threads: 0
Skill Endorsements: 0

It sounds like your file is somehow getting truncated before you write out the data or that you are writing to a non-existing file. You need to check out both of these possibilities in full first.

This outFile.write((char*)this, sizeof(A)); is a particularly poor way to write out the class data to file. There are many ways this could go wrong on a slightly more complex class (one with a virtual base or in fact any base, one with a pointer to allocated data). You should write out the individual data members of the class not perform this type of conversion.

Banfa
Master Poster
705 posts since Mar 2010
Reputation Points: 510
Solved Threads: 109
Skill Endorsements: 5

There's only one data member which is a multi-dimensional array. The casting I have should be fine with that shouldn't it? I know it's not the best way but I was just looking for a way of writing the whole thing at once and reading it in the same way.

As for the truncating, I've gone through and commented out all of the function except the opening and closing. It seems that the file is being truncated upon opening, but I don't understand why. I haven't set the ios::trunc flag, only ios::out and ios::binary. I tried using ios::app but that just forced the put pointer to be at the end on every write.

Reprise
Newbie Poster
20 posts since May 2009
Reputation Points: 10
Solved Threads: 0
Skill Endorsements: 0

There's only one data member which is a multi-dimensional array. The casting I have should be fine with that shouldn't it? I know it's not the best way but I was just looking for a way of writing the whole thing at once and reading it in the same way.

As for the truncating, I've gone through and commented out all of the function except the opening and closing. It seems that the file is being truncated upon opening, but I don't understand why. I haven't set the ios::trunc flag, only ios::out and ios::binary. I tried using ios::app but that just forced the put pointer to be at the end on every write.

The default ios::out flag seams to cause the file-stream recreated the file, you maight do well to try:

std::ofstream ofs("data.bin", std::ios_base::out | std::ios_base::ate);

or

std::ofstream ofs("data.bin", std::ios_base_in | std::ios_base::out);
Benbenzhu
Newbie Poster
7 posts since Apr 2010
Reputation Points: 10
Solved Threads: 2
Skill Endorsements: 0

The default ios::out flag seams to cause the file-stream recreated the file, you maight do well to try:

std::ofstream ofs("data.bin", std::ios_base::out | std::ios_base::ate);

or

std::ofstream ofs("data.bin", std::ios_base_in | std::ios_base::out);

Using ios_base didn't seem to work either. Could it have anything to so with it being a class member function? I'm really just grabbing at straws now!

Reprise
Newbie Poster
20 posts since May 2009
Reputation Points: 10
Solved Threads: 0
Skill Endorsements: 0

Using ios_base didn't seem to work either. Could it have anything to so with it being a class member function? I'm really just grabbing at straws now!

Using iso_base was not the suggestion the suggestion was use iso_base::ate

Banfa
Master Poster
705 posts since Mar 2010
Reputation Points: 510
Solved Threads: 109
Skill Endorsements: 5

Using ios_base didn't seem to work either. Could it have anything to so with it being a class member function? I'm really just grabbing at straws now!

I'm sorry, there are some spelling misstakes I made, and I tried to use the ios::ate flag to solve your problem, but it didn't work, only the way to open the file-stream in read-write mode is correct:

ofstream outFile("data.bin", ios::in | ios::out | ios::binary);

P.S. It doesn't matter to use std::ios_base class or std::ios class, but C++ recommends the std::ios_base class, and deprecates the std::ios class.

Benbenzhu
Newbie Poster
7 posts since Apr 2010
Reputation Points: 10
Solved Threads: 2
Skill Endorsements: 0

I'm sorry, there are some spelling misstakes I made, and I tried to use the ios::ate flag to solve your problem, but it didn't work, only the way to open the file-stream in read-write mode is correct:

ofstream outFile("data.bin", ios::in | ios::out | ios::binary);

P.S. It doesn't matter to use std::ios_base class or std::ios class, but C++ recommends the std::ios_base class, and deprecates the std::ios class.

That was it! Using ios_base::in and ios_base::out fixed it. Thank you!

Reprise
Newbie Poster
20 posts since May 2009
Reputation Points: 10
Solved Threads: 0
Skill Endorsements: 0
Question Answered as of 3 Years Ago by Benbenzhu and Banfa

This question has already been solved: Start a new discussion instead

Post: Markdown Syntax: Formatting Help
 
You
 
© 2013 DaniWeb® LLC
Page generated in 0.0800 seconds using 2.72MB