writing into file

I understand how to write and print values into a BINARY file, but how do you write objects?

For example, if my object of A has 2 values in it, I cannot write it as:

file.write((char*)&A, sizeof(A));
if an object does not contain any pointer you actually can write it to a file like that.
If the object
a. is of a TriviallyCopyable type http://en.cppreference.com/w/cpp/concept/TriviallyCopyable
and b. is not the base class sub-object of an object of a more derived type

we can write the object into a stream with std::ostream::write(), and subsequently restore the state of the object by reading back the same sequence of bytes into the object with std::ostream::read()

Even when these conditions hold, in an overwhelming majority of cases this would still be a terrible design choice.
When you feel the urge to design a complex binary file format, or a complex binary application protocol, it is generally wise to lie down until the feeling passes. ...
...
Designing a textual protocol tends to future-proof your system. ...
ESR in 'The Importance of Being Textual' http://www.faqs.org/docs/artu/ch05s01.html


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
#include <iostream>
#include <type_traits>
#include <memory>

template < typename T > std::ostream& write_bytes( std::ostream& stm, const T& object )
{
    return stm.write( reinterpret_cast< const char* >( std::addressof(object) ), sizeof(object) ) ;
}

// invariant: object is not the base class sub-object of an object of a more derived type
//            *** alert: if it is a base class sub-object, this will engender undefined behaviour ****
// invariant: T is TriviallyCopyable
//            *** alert: if it not TriviallyCopyable, the static assertion will fail ****
template < typename T > std::istream& read_as_bytes( std::istream& stm, T& object )
{
    static_assert( std::is_trivially_copyable<T>::value, "error: object is not of a TriviallyCopyable type" ) ;
    return stm.read( reinterpret_cast<char*>( std::addressof(object) ), sizeof(object) ) ;
}

#include <sstream>

int main()
{
    std::stringstream stm ;

    struct A { int i ; double d ; };
    A a { 1, 2.3 };
    write_bytes( stm, a ) ;
    a = {} ;
    std::cout << a.i << ' ' << a.d << '\n' ; // 0 0
    read_as_bytes( stm, a ) ; // fine
    std::cout << a.i << ' ' << a.d << '\n' ; // 1 2.3

    struct B final { int i ; std::string s; };
    B b { 1, "2.3" };
    write_bytes( stm, b ) ;
    read_as_bytes( stm, b ) ; // *** error: object is not of a TriviallyCopyable type

    struct C : virtual A {};
    C c ;
    c.i = c.d = 0 ;
    A& sub_object = c ;
    write_bytes( stm, sub_object ) ;
    read_as_bytes( stm, sub_object ) ; // **** undefined behaviour **** (base-class sub-object)
}
Ah thank you so much!

Another question, if I had to write 10 objects in to the binary file, is there a faster way then having 10 lines of write?

An std::array of TriviallyCopyable types is TriviallyCopyable, so we can do this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main()
{
    std::stringstream stm ;

    struct A { int i = -3 ; double d = 7.8 ; };

    constexpr std::size_t N = 10 ;
    std::array<A,N> array ;
    std::cout << array[N/2].i << ' ' << array[N/2].d << '\n' ; // -3 7.8

    write_bytes( stm, array ) ;

    array[N/2].i = array[N/2].d = 999 ;
    std::cout << array[N/2].i << ' ' << array[N/2].d << '\n' ; // 999 999

    read_as_bytes( stm, array ) ;
    std::cout << array[N/2].i << ' ' << array[N/2].d << '\n' ; // -3 7.8
}

http://coliru.stacked-crooked.com/a/86b84dd6a4f83934

C++ streams are buffered, so it wouldn't be measurably faster than
1
2
3
for( const A& a : array ) write_bytes( stm, a ) ;
// ...
for( A& a : array ) read_as_bytes( stm, a ) ;

So you're saying that there is no method that's faster than simply writing the write and read function 10 times?
> that there is no method that's faster than simply writing the write and read function 10 times?

That there is no method that's measurably faster than simply writing the write and read function 10 times.
Topic archived. No new replies allowed.