3

This is a C++ question. I have a class that contains a string:

class MyClass{
public:
std::string s;
};

And I have an array of MyClass objects:

MyClass * array = MyClass[3];

Now I want to write the array as binaries into a file. I cannot use:

Ofstream.write((char *)array, 3 * sizeof(MyClass))

because the size of MyClass varies.

How can I use Ofstream.write to achieve the purpose? Many thanks.

Kirill V. Lyadvinsky
  • 97,037
  • 24
  • 136
  • 212
Steve
  • 4,935
  • 11
  • 56
  • 83

6 Answers6

4

Overload operator<< for your class. You could do it as follows:

ostream& operator<< (ostream& os, const MyClass& mc)
{
  return os << mc.s /* << ... other members*/ << endl;
}
Kirill V. Lyadvinsky
  • 97,037
  • 24
  • 136
  • 212
3

In C++ it is usually done using the BOOST serialization class

Programmatically you could do something like this:

Writing:

std::ofstream ostream("myclass.bin",std::ios::binary);
if (!ostream) return; // error!
std::size_t array_size = 3;
ostream.write(reinterpret_cast<char*>(&array_size),sizeof(std::size_t));
for(MyClass* it = array; it != array + array_size; ++it)
{
  MyClass& mc = *it;
  std::size_t s = mc.s.size();
  ostream.write(reinterpret_cast<char*>(&s),sizeof(std::size_t));
  ostream.write(mc.s.c_str(),s.size());
}

Reading

std::ifstream istream("myclass.bin",std::ios::binary);
if (!istream) return; // error!
std::size_t array_size = 0;
istream.read(reinterpret_cast<char*>(&array_size),sizeof(std::size_t));
array = new MyClass[array_size];
for(MyClass* it = array; it != array + array_size; ++it)
{
  MyClass& mc = *it;
  std::size_t s;
  istream.read(reinterpret_cast<char*>(&s),sizeof(std::size_t));
  mc.resize(s);
  istream.read(mc.s.c_str(),s.size());
}
istream.close(); // not needed as should close magically due to scope
1

Write an insertion operator for MyClass, like this, that writes out its members to the stream one by one. Then make a loop that walks your array, writing each member to the stream. Remember to write out the array size at some point too, so you know how many members to read when you read the file back.

And, as Klaim says, make sure you open the stream in binary mode.

moonshadow
  • 86,889
  • 7
  • 82
  • 122
1

A good way of doing this would be to override the << operator for MyClass:

ostream& operator << (ostream& output, const MyClass& myClass)
{
    return output << myClass.Value;
}

You can then simply serialise the strings out of MyClass directly into the file stream:

std::fstream fileStream("output", std::ios::out|std::ios::binary);

for (int i = 0; i < 3; ++i)
    fstream << array[i];
Alan
  • 13,510
  • 9
  • 44
  • 50
1

What exactly do you want to write to file? In C++, you can't make assumptions about the content of an object like you can do in C. std::string for instance typically holds pointers, allocators, string lengths and/or the first few characters. It will certainly not hold the entire char[] you'd get from string::data(). If you have a std::string[3], the three sring::data() arrays will (almost certainly) be non-contiguous, so you will need three writes - each call can only write one contiguous array.

MSalters
  • 173,980
  • 10
  • 155
  • 350
-1

Open the stream in binary mode:

std::fstream filestream( "file.name", std::ios::out | std::ios::binary );
Klaim
  • 67,274
  • 36
  • 133
  • 188