C++ IO file streams: writing from one file to another using operator<< and rdbuf()
I have a question about copying data from one file to another in C++ (fstream) using operator<<. Here is a code snippet that works for me:
#include <fstream>
#include <string>
void writeTo(string &fname, ofstream &out){
ifstream in;
in.open(fname.c_str(),fstream::binary);
if(in.good()){
out<<in.rdbuf();
开发者_运维百科 in.close();
}else{
//error
}
}
I would like to be certain that after writing, the end of input file in stream in
has been reached. However, if I test for in.eof()
, it is false
, despite the fact that checking the input and output files confirms that the entire contents has been properly copied over. Any ideas on how I would check for in.eof()
?
EOF-bit is set when trying to read a character, but none is available (i.e. you have already consumed everything in the string). Apparently std::ostream::operator<<()
does not attempt to read past the end of the string, so the bit is never set.
You should be able to get around this by attempting to access the next character: add in.peek()
before you check in.eof()
. I have tested this fix and it works.
The reason none of the status bits are set in the input file is because
you are reading through the streambuf
, not the istream
; the actual
reading takes place in the ostream::operator<<
, which doesn't have
access to the istream
.
I'm not sure it matters, however. The input will be read until
streambuf::sgetc
returns EOF
. Which would cause the eofbit
to be
set in the istream
if you were reading through the istream
. The
only thing which might prevent this if you were reading through the
istream
is if streambuf::sgetc
threw an exception, which would cause
badbit
to be set in istream
; there is no other mechanism provided
for an input streambuf
to report a read error. So wrap your out <<
in.rdbuf()
in a try ... catch
block, and hope that the implementation
actually does check for hardware errors. (I haven't checked recently,
but a lot of early implementations totally ignored read errors, treating
them as a normal end of file.)
And of course, since you're literally reading bytes (despite the <<
, I
don't see how one could call this formatted input), you don't have to
consider the third possible source of errors, a format error (such as
"abc" when inputing an int).
Try in.rdbuf()->sgetc() == EOF
.
Reference: http://www.cplusplus.com/reference/iostream/streambuf/sgetc/
精彩评论