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!

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.

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.

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);

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!

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

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.

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!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.