35

I'm new to C++ std::stream and I'm making some tests. I have this simple code:

int i = 10;
char c = 'c';
float f = 30.40f;

std::ofstream out("test.txt", std::ios::binary | std::ios::out);
if(out.is_open())
{
    out<<i<<c<<f;
    out.close();
}

As the stream is opened as std::ios::binary I expect in the test.txt file to have the binary representation of i, c and f, but instead I have 10c30.4.

Can you please tell me what I'm doing wrong?

7
  • From cplusplus.com/reference/fstream/ofstream/ofstream binary (binary) Consider stream as binary rather than text. Commented Feb 8, 2013 at 7:45
  • 1
    Okay, on to the POSIX definitions of text file streams vs. binary file streams then :) (Hint: why would writing text to a binary file result in something else than text?) Commented Feb 8, 2013 at 7:46
  • 1
    @Felics: the standard does not specify what "binary" actually means. In fact on some platforms it has no effect (e.g. on POSIX). Commented Feb 8, 2013 at 7:47
  • 9
    To be perfectly clear: +1 for this question. I think it is interesting to find that documentation on this is very sketchy. It is apparently "assumed" to be obvious. More people might be confused, which makes this a perfect Stack Overflow candidate. Commented Feb 8, 2013 at 7:48
  • 3
    @Felics: your last sentence makes no sense. ISO says that opening an fstream with binary|out is equivalent to fopen with "wb" mode. Now, when you say "I have the expected result" it means that you called fwrite, which corresponds to ostream::write. But your code here uses operator <<, which corresponds to, e.g. fprintf(out, "%d", i) for integers. Commented Feb 8, 2013 at 8:00

2 Answers 2

18

std::ios::binary promises to not do any line-end conversions on the stream (and some other small behavioral differences with text streams).

You could look at

Here's an example using Boost Spirit Karma (assuming Big-Endian byte ordering):

#include <boost/spirit/include/karma.hpp>
namespace karma = boost::spirit::karma;

int main()
{
    int i = 10;
    char c = 'c';
    float f = 30.40f;

    std::ostringstream oss(std::ios::binary);
    oss << karma::format(
            karma::big_dword << karma::big_word << karma::big_bin_float, 
            i, c, f);

    for (auto ch : oss.str())
        std::cout << std::hex << "0x" << (int) (unsigned char) ch << " ";
    std::cout << "\n";
}

This prints

0x0 0x0 0x0 0xa 0x0 0x63 0x41 0xf3 0x33 0x33 
Sign up to request clarification or add additional context in comments.

2 Comments

I've added a demo based on Karma, see also here: http://liveworkspace.org/code/4B5okj
That's not quite "end of story", there are various possible transformations that can be performed on text files, including that the data read back may differ from the data written (e.g. trim trailing space), and some file operations such as fseek behave differently for each type.
18

In order to write raw binary data you have to use ostream::write. It does not work with the output operators.

Also make sure if you want to read from a binary file not to use operator>> but instead istream::read.

The links also provide examples how you can handle binary data.

So for your example:

int i = 10;
char c = 'c';
float f = 30.40f;

std::ofstream out("test.txt", std::ios::binary | std::ios::out);
if(out.is_open())
{
    out.write(reinterpret_cast<const char*>(&i), sizeof(i));
    out.write(&c, sizeof(c));
    out.write(reinterpret_cast<const char*>(&f), sizeof(f));
    out.close();
}

6 Comments

beware of UB and unportability when doing this. I'd suggest using well tested libraries to handle this for you, and account for endianness (Boost Spirit, Serialization, protobuf etc.)
Yes, you are right. But I just wanted to point to an answer with plain C++ without any boost or other libraries.
E.g. the sample technically requires reinterpret_cast<const char*> to not invoke Undefined Behaviour, I think. (PS. I did point to the answer in plain C++ too :))
@sehe That (= the code not invoking UB) is guaranteed by the standard, actually. The result of doing this, now that is unspecified.
I think you're missing a & or three. And a couple of sizeofs.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.