28

I have the following code and it works pretty good (other than the fact that it's pretty slow, but I don't care much about that). It doesn't seem intuitive that this would write the entire contents of the infile to the outfile.

// Returns 1 if failed and 0 if successful
int WriteFileContentsToNewFile(string inFilename, string outFilename)
{
    ifstream infile(inFilename.c_str(), ios::binary);
    ofstream outfile(outFilename.c_str(), ios::binary);

    if( infile.is_open() && outfile.is_open() && infile.good() && outfile.good() )
    {
        outfile << infile.rdbuf();

        outfile.close();
        infile.close();
    }
    else
        return 1;

    return 0;
}

Any insight?

Brian T Hannan
  • 3,925
  • 18
  • 56
  • 96
  • 4
    I would add that explicit calls to `close()` are not needed. Destructors would do the same anyway. And that saves some lines. ;) – Adam Badura May 22 '15 at 22:15

3 Answers3

30

iostream classes are just wrappers around I/O buffers. The iostream itself doesn't do a whole lot… mainly, it provides operator>> formatting operators. The buffer is provided by an object derived from basic_streambuf, which you can get and set using rdbuf().

basic_streambuf is an abstract base with a number of virtual functions which are overridden to provide a uniform interface for reading/writing files, strings, etc. The function basic_ostream<…>::operator<<( basic_streambuf<…> ) is defined to keep reading through the buffer until the underlying data source is exhausted.

iostream is a terrible mess, though.

Rain
  • 3,416
  • 3
  • 24
  • 40
Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
19

Yes, it's specified in the standard and it's actually quite simple. rdbuf() just returns a pointer to the underlying basic_streambuf object for the given [io]stream object.

basic_ostream<...> has an overload for operator<< for a pointer to basic_streambuf<...> which writes out the contents of the basic_streambuf<...>.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 2
    But wouldn't operator<< just write out one chunk? It's not easy to see that it will write out the whole thing as one chunk. I understand it's a pointer to it but does that pointer contain the entire data as one chunk? I'm still a little confused. – Brian T Hannan Jan 26 '10 at 19:12
  • 3
    I'm not quite sure what you are driving at with 'one chunk'? It's specified to output the contents of the pointed to `streambuf` character by character until the end of the buffer is reached or there is an error outputting it. The `streambuf` is a class instance and whether it stores its controlled sequence in contiguous memory or not is not specified and can't be inferred from the interface. – CB Bailey Jan 26 '10 at 19:17
  • Ok, it does it character by character until the end of the buffer is reached. How do you know that? I didn't see that from the interface provided. – Brian T Hannan Jan 26 '10 at 19:33
  • @Brian: It's specified in the standard. – GManNickG Jan 26 '10 at 20:24
  • Where is this standard documentation you are speaking of. I have looked at: http://msdn.microsoft.com/en-us/library/whhe46xz%28VS.80%29.aspx and http://www.cplusplus.com/reference/iostream/ios/rdbuf/ – Brian T Hannan Jan 26 '10 at 20:55
  • http://stackoverflow.com/questions/81656/where-do-i-find-the-current-c-or-c-standard-documents – CB Bailey Jan 26 '10 at 21:01
  • 5
    So there's like 10,000 standards with weird names that only people at ISO can possibly understand what they mean. Not only do you not know what you're getting, but it costs $300 for a real standard from ISO. This is ridiculous. I just want to know one simple little thing and I have to buy a stupid standard. This information should be free and readily available so people can make better code. LAME!! – Brian T Hannan Jan 26 '10 at 21:14
  • @Brian T Hannan : The documentation of ostream::operator<< is available, among many other places, on MSDN: http://msdn.microsoft.com/en-us/library/ba4ae8wb(VS.80).aspx. No need to buy the standard for that. – Éric Malenfant Jan 26 '10 at 21:29
  • 2
    @Brian T Hannan: If you read the answers to the linked question you'll find links to freely available drafts of all the relevant standards. These will be very close to the actual standards and are going to be the most reliable free reference for definitive answers. – CB Bailey Jan 26 '10 at 21:36
  • 1
    @Eric Malenfant : Thanks! I was looking in the wrong place. I was looking in the ifstream documentation, but really where the work is being done is in "ostream::operator<<" This is much clearer now. – Brian T Hannan Jan 26 '10 at 23:32
1

A quick look at the source code shows that basic_ofstream is the wrapper around basic_filebuf.

asterisk
  • 11
  • 1