Re: ofstream random access not working / developer error
On Jan 24, 11:31 am, Lars Uffmann <a...@nurfuerspam.de> wrote:
James Kanze wrote:
[...]
My first question would be: how portable do you need to be?
You've made a couple of assumptions that the standard doesn't
guarantee, but which do often hold.
Thanks for pointing that out - especially the information
about the streampos type - I'll recheck my code with regards
to that. I don't need to be portable in this case, but I like
to be.
There is no standard portable way of getting the length of a
file, other than by reading it, and counting how many bytes
you've read. I tend to use stat/fstat when I need the size of a
file, but my portability concerns are limited to Unix and Unix
look-alikes. As I said, I think that seeking to the end, then
converting the streampos returned from a [pg]tell to a
streamoff, and the streamoff to an integer type of sufficient
size, should be portable to most widely used systems. You may
need an explicit conversion to do it, however, since streamoff
can be a user defined type, rather than just a typedef to an
integral type (but again, I wouldn't really expect this under
Unix or Windows).
Attention: streampos is a fairly complex type, containing
information about state in the case of multibyte encodings.
I suppose multibyte encodings only apply to non binary open
modes?
Nope. I'd forgotten to mention this, but you almost certainly
want to imbue the file with the "C" locale. The "encoding" is
independent of the binary/text mode, and depends strictly on the
imbued locale.
And of course, the type streampos doesn't change---it contains
the state information even if the imbued locale doesn't use it.
Since you suggested the use of long or long long? I'll do that
then, since I am definitely working with binary.
You'll still get into trouble with things like padding and byte
order (and at least theoretically, representation, but there are
very, very few systems today that don't use 2's complement).
Define a format (or use an existing one, like XDR), format your
data to it, and output the formatted data.
(If you call ostream::write with anything but a char const*,
you'll need a reinterpret_cast. And as we all know,
reinterpret_cast means that the code is not portable, that it
depends on some aspect of the implementation.)
I seem to recall hearing that after seeking to the end of file,
some implementations set eofbit. If so, the write will fail.
Ouch. That'd be nasty. Got any sources on that?
Not directly. Someone was complaining about it in one of the
forums, I think. Technically, the implementation is (or was---I
think the standard has been reworded here) correct. Strictly
speaking, the eofbit means that the next read is guaranteed to
encounter eof, and if you've done a seek to the end of file,
that condition is true, so an implementation is (or was) allowed
to set it. The problem is that if the bit is set, the next
operation will fail, regardless of what it is. And that once
set, it will only be reset by a clear(). (A more reasonable
approach might be that the next read will fail, but all other
operations will be attempted without checking the bit, and that
it is reset on a seek.)
At any rate, you should be checking for errors after each
action; if all actions fail after a seek to end of file, you
know where the problem lies.
If I seek the end of the file for the PUT pointer, that should
definitely not happen. For the get poiner I can understand why
and actually that is perfectly acceptable behaviour.
The problem is that in filebuf, the put pointer and the get
pointer are one. (At the streambuf/iostream level, it is
unspecified whether there is a single position pointer, or
separate position pointers for the get and put areas.
stringbuf/sstream uses separate pointers, filebuf/fstream a
unified pointer.)
I'd tend to throw in an "indexFile.clear()" before the
write, just to be sure.
That's actually the solution to my initial problem of
resetting fstr properly after a failed open() :) But I guess I
was playing around with the solution already at the time your
post got to my newsserver.
And of course, you definitely want to check whether the
write succeeded---it will also fail, for example, if the
disk is full.
Of course. As I said elsewhere - I'll do some thorough error
checking once I got a working application :)
That's one aspect. The other point I was trying to make was
that error checking could help you find where things were going
wrong. When writing, for example, I'll often defer error
checking until after the close. If anything went wrong, the
error will still be there. But during debugging, it might be
useful to know just how far you got before the error occurred.
Right now I need a new GUI engine - Widestudios Native
Application Builder just doesn't cut it. Going for a wxWidgets
Tutorial now - possibly Qt.
The best I've found to date is Java Swing, over a Corba
interface:-).
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34