Mark
Mark

Reputation: 2112

ostream::write not writing entire struct?

I'm trying to export various values, such as ints and simple structs, to a binary file. Here's some code:

#include <iostream>
#include <fstream>
#include <cstdint>
using namespace std;

template<class T> void writeToStream(ostream& o, T& val)
{
    o.write((char*)&val, sizeof(T));
    cout << o.tellp() << endl;  //always outputs 4
}

struct foo {
    uint16_t a, b;
};

int main()
{
    foo myFoo = {42, 42};
    ofstream test("test.txt", ios::binary);
    writeToStream(test, myFoo);
    test.close();
}

The program should generate an output file 4 bytes long. But when I open it, it's only 2 bytes long. If I change myFoo.a and myFoo.b to contain values of 256 or more (requires more than 1 byte to store), then the file becomes 4 bytes long. I'm using the Visual Studio 11 Developer Preview on Win7; I haven't checked to see if the same happens on other systems or compilers. How can I make it output correctly for values of a or b under 256?

Upvotes: 1

Views: 262

Answers (2)

thb
thb

Reputation: 14464

I have cleaned up your code as follows. Though I do not know why the old code output two bytes, the new code does output four.

#include <iostream>
#include <fstream>
#include <cstdint>
using std::cout;
using std::endl;
using std::uint16_t;
using std::ostream;
using std::ofstream;
using std::ios;

template <class T> void writeToStream(ostream& o, T& val)
{
    o.write(reinterpret_cast<char *>(&val), sizeof(T));
    cout << o.tellp() << endl;  //always outputs 4
}

struct foo {
    uint16_t a, b;
};

int main()
{
    foo myFoo = {42, 42};
    ofstream test("test.txt", ios::binary);
    writeToStream(test, myFoo);
    // Just let the stream "test" pass out of scope.
    // It closes automatically.
    //test.close();
    return 0;
}

(My standard library lacks cstdint, so I used short rather than uint16_t, but I doubt that this matters.)

The std::ofstream type is derived from std::ostream. The writeToStream() function is happier, or at least more regular and more general, if passed a plain std::ostream. Also, for information: to issue using namespace std; is almost never recommended in C++.

Good luck.

Upvotes: 0

David Schwartz
David Schwartz

Reputation: 182827

A file can only be read back by a program that understands the format in which it was stored. Notepad++ has no understanding of the format in which your file was stored, so it has no ability to read it back and render it sensibly. Either write the file in a format Notepad++ understands, such as ASCII text, or only read the file with a program that understand the format you wrote it in.

Upvotes: 2

Related Questions