2

When I open an ofstream object for a file I do:

std::ofstream outFile("myfile");

Then I want to want to some numbers to it, but the only method it has is the ::write() method which takes a const char* and a size. So I could do:

int temp = 5;
outFile.write((const char*)&temp, sizeof(int));

There's also the input operator <<, but I don't want formatted input, I want it written as pure binary data. I was wondering if there's a way I can write directly like:

outFile.write(12, sizeof(int));
outFile.write(10, sizeof(int));

Instead of creating temporaries, or previously allocating an array. I'm thinking that the limitation is that the only value that I could put in the argument would be an RValue, and there doesn't seem there's a way of making an lvalue from an rvalue. I guess technically the rvalue lasts until the end of the line, so if there was the opposite of std::move it could work. Is it possible to do this writing numbers directly?

Garf365
  • 3,619
  • 5
  • 29
  • 41
Zebrafish
  • 11,682
  • 3
  • 43
  • 119
  • Your only options for writing unformatted data into a `std::ostream` are `write()`, and `put()`. That's it. Pick one. – Sam Varshavchik Oct 06 '17 at 13:05
  • I don't know your final application, but with information given, I probably choose to forget `ostream` to come back to plain old C like "(f)read, (f)write, (f)open" (https://stackoverflow.com/questions/17598572/read-write-to-binary-files-in-c) – Garf365 Oct 06 '17 at 13:07
  • Just for context, I'm writing a bunch of buffers in, so ofstream::write() is fine, but what I wanted to do was to first put in a couple of header info, like size, so like insert a quick number or two at the beginning. Seemed way weird to first make a temporary first to do this, but oh well. – Zebrafish Oct 06 '17 at 13:09
  • the way to make an lvalue from a rvalue is to create temporary: `auto lvalue = whatever_that_gives_you_a_rvalue;` ;) – 463035818_is_not_an_ai Oct 06 '17 at 13:09
  • 1
    Write (inline) function that writes `int` to `ofstream`. Problem solved. – Slava Oct 06 '17 at 13:10
  • Really it's no major problem, I was just wondering. Hmm, inline function? Lambda to the rescue? – Zebrafish Oct 06 '17 at 13:13
  • @Garf365 how that would change requirement to take memory address of the variable? – Slava Oct 06 '17 at 13:20

3 Answers3

3

So I could do:

You can do much better:

void writeInt( std::ostream &os, int i )
{
    os.write( reinterpret_cast<const char*>(&i), sizeof( i ) );
}

then use it with rvalue or lvalue:

int i = 0;
writeInt( f, i );
writeInt( f, 5 );
writeInt( f, funtionReturnsInt() );

and you should do that anyway, as you may later want to change format you store/load data and this way you need to change it only once.

Slava
  • 43,454
  • 1
  • 47
  • 90
2

I like to use a template which can write any primitive type:

template<typename T>
void write_item(std::ostream& os, const T& item) {
    os.write(reinterpret_cast<const char *>(&item), sizeof T);
}

Of course, you would probably want to put some constraints in there to avoid trying to do this with more complex types.

Ferruccio
  • 98,941
  • 38
  • 226
  • 299
0

Use "<<" operator . For example os << "123"; Any string or object can be written to ostream without type casting.

Vijaya Prakash
  • 111
  • 1
  • 5