Saving complex object data to a file

Hello! I was trying to create a file where object data could be written, so that different programs could use it. I'm having trouble understanding just exactly what goes on when a program writes to a file, so I hope somebody could help me out.

First, this program saves an object of the class "Something" to a file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <fstream>
#include <iostream>

using namespace std;

class something {

	public:

	int weight;
	int size;

}thing1;


int main()
{

	thing1.size = 1;

	ifstream::pos_type size = sizeof(thing1);
	Something * memblock;
	memblock = &thing1;

	ofstream save1;
	save1.open("saved", ios::binary);
	save1.seekp(0,ios::beg);
	save1.write((char*)&memblock,size);
	save1.close();
	
	return 0;
}


First, I assume I must use a binary file to store this kind of data. Then, since the write method only takes char pointers as its first arguement, I typecasted my object pointer as a char*. As I understand it, this tells the program to take the values stored in the memory address of thing1, and writes it to a file called "saved.

The second program has the same "Something" class, and it's supposed to read from the "saved" file to assign its values to a new object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <fstream>

using namespace std;

class Something {

	public:

	int weight;
	int size;
};

int main()
{
	ifstream file;
	file.open("saved",ios::binary);

	int beginning,end;

	beginning = file.tellg();
	file.seekg(0, ios::end);
	end = file.tellg();

	ifstream::pos_type size = (fin - inicio);
	Something * memblock = new Something;

	Something thing2;

	file.seekg(0,ios::beg);
	file.read((char*)&memblock,size);
	file.close();

	cout << &memblock << endl;
	thing2 = *memblock;

	cout << thing2.size << endl;

	return 0;
}


Both programs compile and run, but in the end, when I try to get the size value of thing2, the output is "0", when it should be "1".

I'm pretty surprised that it actually compiled, since I'm not really sure what is going on.
1
2
save1.open("saved", ios::binary);
file.open("saved",ios::binary);

you forgot the type of file (extension)... the others, don't noticed yet... :D
The file has no extension. I'm using Linux : )
I would not worry about using binary to store your object. It is fiddly and non-portable. The natural way to serialize objects in C++ is using the insert and extraction operators. You can define them like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <fstream>
#include <iostream>

class Something
{
public:
	int weight;
	int size;

	// Insertion operator
	friend std::ostream& operator<<(std::ostream& os, const Something& s)
	{
		// write out individual members of s with an end of line between each one
		os << s.weight << '\n';
		os << s.size;
		return os;
	}

	// Extraction operator
	friend std::istream& operator>>(std::istream& is, Something& s)
	{
		// read in individual members of s
		is >> s.weight >> s.size;
		return is;
	}
};

int main()
{
	Something s1;
	Something s2;

	s1.weight = 4;
	s1.size = 9;

	std::ofstream ofs("saved.txt");

	ofs << s1; // store the object to file
	ofs.close();

	std::ifstream ifs("saved.txt");

	// read the object back in
	if(ifs >> s2)
	{
		// read was successful therefore s2 is valid
		std::cout << s2 << '\n'; // print s2 to console
	}

	return 0;
}
Thanks a lot for the reply, Galik. While I'm sure this works, I don't understand what this is:

 
friend std::ostream& operator<<(std::ostream& os, const Something& s)


Are you overloading the << operator for this class? If that's so, why do you need to declare it as a friend?

EDIT: Also, why "std::ostream& operator<<" instead of "std::ostream operator <<" ?

I'm reading up on overloading right now. I just wanted to note that I read your post, and appreciate it :D
Last edited on
Yes I am overloading the << operator.

When you declare/define a friend function:
1
2
3
4
class Stuff
{
    friend std::ostream& operator<<(std::ostream& os, const Something& s);
}

It is not really part of the class like a member function, but it has access to the private data of the class. This is important because the operator<< needs to be able to store the private data. In your example it's not really necessary to make it a friend because you don't have any private data members. However, usually classes do so I was being consistant in making it a friend function.

I returned a reference to the std::ostream because you can not make copies of std::ostream objects. And also you want to return the same std::ostream object that you passed in so that you can chain << operators like:
 
std::cout << s1 << '\n';

That works because std::cout << s1 returns std::cout so that the following << '\n' also goes to std::cout.
Topic archived. No new replies allowed.