The C++ standard library's stream I/O facilities are type-safe and very convenient for performing formatted (i.e. human readable) I/O. But they offer only rudimentary and not very type-safe operations for performing unformatted binary I/O. Although formatted I/O is often preferable, some applications need the speed and storage efficiency of unformatted binary I/O or need to interoperate with third-party applications that require unformatted binary file or network data formats.
Standard library streams can be opened with filemode
std::ios_base::binary, so binary I/O is possible. But the only
unformatted I/O functions available are get(), put(),
read(), and write(). These operate only on char
or array of char (with length explicitly specified), so require the
user to write casts, are hard to use, and are error prone.
There have been many requests on Boost and various C++ newsgroups for unformatted binary I/O. For example, in 2003 Neal Becker wrote:
I wonder if anyone has code for implementing unformatted I/O? What I have in mind is for the simple case where the application that reads data knows the data types, so this is not as complicated as the general marshalling situation.
This proposal provides a simple solution that works with standard library
input and output streams. The one caveat is that the stream must be opened with filemode std::ios_base::binary
to avoid certain data values being treated as line endings.
namespace boost
{
template <class T>
unspecified-type-1<T> bin(const T& x);
template <class T>
unspecified-type-2<T> bin(T& x);
template <class T>
std::ostream& operator<<(std::ostream& os, unspecified-type-1<T> x);
template <class T>
std::ostream& operator<<(std::ostream& os, unspecified-type-2<T> x);
template <class T>
std::istream& operator>>(std::istream& is, unspecified-type-2<T> x);
}
unspecified-type-1 and unspecified-type-2
are implementation supplied types.
int main()
{
fstream f("binary_stream_example.dat",
std::ios_base::trunc | std::ios_base::in | std::ios_base::out | std::ios_base::binary);
int32_t x = 0x01020304;
int32_t y = 0;
f << bin(x);
f.seekg(0);
f >> bin(y);
BOOST_ASSERT(x == y);
return 0;
}
The file produced with be four bytes in length. On a big-endian machine, the contents in hexadecimal are:
01020304
On a little-endian machine, the contents in hexadecimal are:
04030201
Last revised: 24 April, 2011
© Copyright Beman Dawes, 2009, 2011
Distributed under the Boost Software License, Version 1.0. See www.boost.org/ LICENSE_1_0.txt