Re: fstream::write does not export partially filled buffers
Denise Kleingeist wrote:
Rune Allnor wrote:
#include <fstream>
#include <iostream>
Nothing from the header <iostream> is used in this program and
it can be removed.
fstream fin;
fin.open(fname,ios_base::binary|ios_base::out|ios_base::in);
I prefer to open the file in the constructor. Basically, I
define object when I can properly initialize them and I do so.
Les gouts et les couleurs, as they say in French. fstream has a
default constructor, and so is, by definition, correctly
initialized after construction. And of course, whether you open
in the constructor, or after, you still have to test whether the
open succeeded. It's not as if specifying the name in the
constructor guarantees you a usable object.
In this case, I'd probably open the file in the constructor,
too. But only because it is one less line of code; there's no
difference otherwise. What I'd really like is for the open
function to return something I could test, so I could use it
like I use all of the other iostream functions:
if ( ! fin.open( ... ) ) {
// Handle error...
}
fin.seekg(0,ios::end);
long int fsize = fin.tellp();
This doesn't work! For one, the type returned from "tellp()"
is "pos_type" which effectively boils down to
"std::fpos<mbstate_t>". This type is required to have an
explicit conversion to "off_type" which in turn can be
implicitly converted to a signed integer. If the conversion is
indeed only explicit or if "off_type" is not "long int" the
conversion fails.
Just a nit: the conversion works as long as off_type isn't a
user defined type (and, of course, the conversion of pos_type to
off_type is implicit). Where "works" means "passes the
compiler", of course; there's still no guarantee that you get
anything directly usable.
Also, the result of the conversion is not
the file size anyway if the used conversion is not a fixed
width encoding (e.g. for UTF-8).
The issues are somewhat different if the file is being read as
binary. In locale "C", of course---given that the file was
opened in binary mode, the user probably meant to imbue locale
"C" as well, and either forgot, or wasn't aware of the
necessity to be able to read and write transparently. (Note
that the original poster was trying to modify data in place,
which pretty much means that transparent access is necessary.)
[...]
fin.read(buffer,buffersize);
The above function will set "std::ios_base::failbit" if the "buffersize"
characters cannot be read. Once this flag is set, the stream will not
proceed with any of the stream operations until this flags is cleared
again. Here is how I would write the main part of the program:
Which is, of course, the real problem with the code. Along with
the fact that he is trying to use eof() to detect end of file,
which doesn't work right.
#include <fstream>
#include <algorithm>
#include <vector>
int main(int argc, char* argv[])
{
char fname[] = "testdata.txt";
std::fstream fin(fname, std::ios_base::in | std::ios_base::out |
std::ios_base::binary);
Come now. I'm sure that you'd check that the open succeeded.
std::vector<char> buffer(4194304);
for (std::ios::pos_type rpos = fin.tellg(), wpos = rpos;
0 < fin.read(&buffer.front(), buffer.size()).gcount(); )
Which wouldn't get past code review in any place I've worked.
Too complicated, and too obscure. I think I'd go with a
separate function, which repositions the file, trims the
buffer to the desired length, and returns success or failure.
Something along the lines of:
bool
readAndReposition(
istream& source,
std::vector< char >&dest )
{
assert( dest.size() > 0 ) ;
if ( ! source ) {
dest.resize( 0 ) ;
} else {`
std::ios::pos_type pos = source.tellg() ;
source.read( &dest[ 0 ], dest.size() ) ;
dest.resize( source.gcount() ) ;
if ( dest.size() != 0 ) {
source.clear() ;
if ( ! source.seekg( pos ) ) {
dest.resize( 0 ) ;
}
}
}
return dest.size() != 0 ;
}
Note that it also handles some of the error handling that you
missed in your loop. (Of course, the error handling wasn't
present in the original code, either. But I rather think it is
a good idea; you do want to know if something goes wrong.)
--
James
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]