According C++ Standard 27.8.1.3 Table 92 when a file stream is
opened with ios_base::out | ios_base::app it should behave like fopen
with "a" open mode.But I discovered that fopen is platform dependent,
under my Linux file pointer is set at end of file after it has been
open on Windows it stays at beginning. So what should a C++ Standard
implementation do:
1. Follow platform dependent fopen behavior ?
2. Always stay at the beginning of file once the file is open?
3. Always move to the end of file once the file is open (like ate) ?
Thanks for your feedback.
Bests
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
> Hello
>
> According C++ Standard 27.8.1.3 Table 92 when a file stream is
> opened with ios_base::out | ios_base::app it should behave like fopen
> with "a" open mode.But I discovered that fopen is platform dependent,
> under my Linux file pointer is set at end of file after it has been
> open on Windows it stays at beginning. So what should a C++ Standard
> implementation do:
The "a" mode to fopen() is not platform dependent. It is specifically
defined in the C standard, from which the C++ standard inherits its
behavior:
"Opening a file with append mode ('a' as the first character in the
mode argument) causes all subsequent writes to the file to be forced
to the then current end-of-file, regardless of intervening calls to
the fseek function. In some implementations, opening a binary file
with append mode ('b' as the second or third character in the above
list of mode argument values) may initially position the file position
indicator for the stream beyond the last data written, because of null
character padding."
Note that it does not make any difference where the file pointer is
after opening the file, or even after any seek operation. What the C
and therefore C++ standards require is that all write operations occur
at the end of the file, extending it.
> 1. Follow platform dependent fopen behavior ?
Again, I find it very unlikely that there is such a serious defect in
your compiler's library. How are you determining the file pointer
position? There is no requirement that it be at any particular point
at any particular time. The only real requirement imposed on
fopen("name", "a") is that all writes are forced to the end.
If you open an existing file on your Windows implementation and write
to it, if it writes anywhere else than at the end after all existing
contents, they your compiler's library is horribly defective, not
platform dependent.
> 2. Always stay at the beginning of file once the file is open?
> 3. Always move to the end of file once the file is open (like ate) ?
Actually, none of the above. What you should do is:
4. Always move to the end of the file before each and every write
operation.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
According to the C standard, the effect of the "a" flag is "all write to
the file are forced to the current end-of-file, regardless of
intervening calls to the fseek function." In particular, it does not
require nor imply that the initial position of the stream should be set
at the end of file, so you shouldn't rely on that behaviour.
> 2. Always stay at the beginning of file once the file is open?
Moving to the beginning of the file is pointless, as any write operation
will move you at the end-of-file anyway.
> 3. Always move to the end of file once the file is open (like ate) ?
Using ios::ate is a good option, if you need consistent behaviour.
However, in the minimal open-append-close scenario, the position of the
file pointer is irrelevant (all writes occurs at eof anyway) so why care?
HTH,
Ganesh
Actually that's the only thing he should *not* do, because it's the only
thing that the implementation guarantees to always automatically occur.
Ganesh
--
> Jack Klein ha scritto:
> > On Tue, 22 Jul 2008 21:02:14 CST, francois...@free.fr wrote in
> > comp.lang.c++.moderated:
> >
> >> 2. Always stay at the beginning of file once the file is open?
> >> 3. Always move to the end of file once the file is open (like ate) ?
> >
> > Actually, none of the above. What you should do is:
> >
> > 4. Always move to the end of the file before each and every write
> > operation.
> >
>
> Actually that's the only thing he should *not* do, because it's the only
> thing that the implementation guarantees to always automatically occur.
I interpreted the OP's original question "So what should a C++
Standard implementation do" as indicating that he was trying to
implement part of a standard C++ library. In which case, my wording
was OK.
On the other hand, his wording is somewhat ambiguous. Regardless, my
reply would have been better for any interpretation of his meaning if
I had written "What a conforming implementation must do" instead of
"What you should do".
Thanks for the correction.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
"In some implementation" means for me that it is implementation
dependent :-).
I am just in the situation you describe that is to say in binary mode
under a platform where binary/text mean something, I haven't check
however that test mode change something. None of the runtime I have
been able to test are wrong, they all write to the end of file. But
the position in the file given by ftell after the call to fopen is
implementation dependent and as C++ Standard says that C++ behavior
should be just as fopen behavior then C++ behavior is not well
defined. Can it be consider as a Standard flow ? Or is it simply that C
++ users shouldn't expect any position after opening a file, what
should be the value of invalid_assert in following code ?
{
ofstr ofstr("foo.txt");
ofstr << "bar";
}
{
ofstream ofstr("foo.txt", ios_base::app);
bool invalid_assert = ???;
assert(invalid_assert || ofstr.tellp() == ofstream::pos_type(3));
}
Thanks
--