iostreams equivalent to C's fopen "r+"

D

Dave O'Hearn

I want to open a file for both reading and writing, but when I do
"ios::in|ios::eek:ut" with an fstream, it creates the file if it doesn't
already exist. I don't like that last part. C's fopen has the "r+"
mode, where the file will open for reading "+ also writing", but it
will not create a new file if one isn't already there; it fails with
an error. POSIX also has this behavior with it's 'open' call, you just
leave the 'create' bit out, and you can open for read/write without
creating.

But I can't figure out how to do this with iostreams. The only
ios::eek:penmode values I know of are: app, ate, binary, in, out,
trunc... and none of them have to do with create-if-doesn't-exist. So
far as I can tell, with iostreams, that is implicit in ios::eek:ut,
whether you want it or not.

Is there a way, or do I have to open the file for reading to check
that it exists, then close it and reopen it for read/write?

Thanks in advance for any advice.
 
M

Mike Wahler

Dave O'Hearn said:
I want to open a file for both reading and writing, but when I do
"ios::in|ios::eek:ut" with an fstream, it creates the file if it doesn't
already exist.

It shouldn't.
I don't like that last part. C's fopen has the "r+"
mode, where the file will open for reading "+ also writing", but it
will not create a new file if one isn't already there; it fails with
an error. POSIX also has this behavior with it's 'open' call, you just
leave the 'create' bit out, and you can open for read/write without
creating.

But I can't figure out how to do this with iostreams.

The following works for me (assuming that the file whose name
is specified does not previously exist):

#include <cstdlib>
#include <fstream>
#include <ios>
#include <iostream>

int main()
{
std::fstream f("C:/nonexistent.file", std::ios::in | std::ios::eek:ut);
if(!f)
{
std::cerr << "could not open file\n";
return EXIT_FAILURE;
}

return 0;

}

Output:

could not open file


Visual inspect confirms that the file was not created.
The only
ios::eek:penmode values I know of are: app, ate, binary, in, out,
trunc... and none of them have to do with create-if-doesn't-exist. So
far as I can tell, with iostreams, that is implicit in ios::eek:ut,
whether you want it or not.
No.


Is there a way, or do I have to open the file for reading to check
that it exists, then close it and reopen it for read/write?

See above. What implementation are you using?

-Mike
 
C

Chuck McDevitt

Dave O'Hearn said:
I want to open a file for both reading and writing, but when I do
"ios::in|ios::eek:ut" with an fstream, it creates the file if it doesn't
already exist. I don't like that last part. C's fopen has the "r+"
mode, where the file will open for reading "+ also writing", but it
will not create a new file if one isn't already there; it fails with
an error. POSIX also has this behavior with it's 'open' call, you just
leave the 'create' bit out, and you can open for read/write without
creating.

But I can't figure out how to do this with iostreams. The only
ios::eek:penmode values I know of are: app, ate, binary, in, out,
trunc... and none of them have to do with create-if-doesn't-exist. So
far as I can tell, with iostreams, that is implicit in ios::eek:ut,
whether you want it or not.

Is there a way, or do I have to open the file for reading to check
that it exists, then close it and reopen it for read/write?

Thanks in advance for any advice.

You are obviously on Windows. As far as I know, it's implementation
defined if the file gets created or not.
In the Windows implementation it does, on most Unix systems it does not.

Windows has a ios::_Nocreate you can set.
 
M

Mike Wahler

Chuck McDevitt said:
You are obviously on Windows. As far as I know, it's implementation
defined if the file gets created or not.
In the Windows implementation it does, on most Unix systems it does not.

The example I tested and posted was done with MSVC++v6.0 on Win982E.
The file was not created.

-Mike
 
D

Dave O'Hearn

Chuck McDevitt said:
You are obviously on Windows. As far as I know, it's implementation
defined if the file gets created or not.
In the Windows implementation it does, on most Unix systems it does not.

Windows has a ios::_Nocreate you can set.

I have two systems, a Red Hat 6.2 with gcc 2.95.3, and a Red Hat 9
with gcc 3.2.2. The ancient system has an ios::nocreate, and it's
definately creating the files unless I put ios::nocreate in there. I
don't know what the newer system does by default, but it has no
ios::nocreate, so I can't put that in my code without conditional
compilation, or it won't compile on Red Hat 9 at all.

I think I have to use the hack I found online, where you open for 'in'
mode first, then if it succeeds, reopen for in|out mode. It's odd that
'nocreate' isn't standard, since it's easy enough for a library to
fake even if the OS doesn't support it... and if the library doesn't
fake it, all the user code has to fake it instead. But that didn't
happen, so I will just have to fake it myself, oh well. Thanks.
 
R

Rick Noelle

I have two systems, a Red Hat 6.2 with gcc 2.95.3, and a Red Hat 9
with gcc 3.2.2. The ancient system has an ios::nocreate, and it's
definately creating the files unless I put ios::nocreate in there. I
don't know what the newer system does by default, but it has no
ios::nocreate, so I can't put that in my code without conditional
compilation, or it won't compile on Red Hat 9 at all.

I think I have to use the hack I found online, where you open for 'in'
mode first, then if it succeeds, reopen for in|out mode. It's odd that
'nocreate' isn't standard, since it's easy enough for a library to
fake even if the OS doesn't support it... and if the library doesn't
fake it, all the user code has to fake it instead. But that didn't
happen, so I will just have to fake it myself, oh well. Thanks.

Hi Dave,

This does the trick for me on RedHat 9.0 with gcc 3.2.2. If the file does
not exist, it will not be created. The excellent book "C++ Primer Plus
4th Edition" by Stephen Prata has a table that lists the C modes like r+
with their equivalent C++ modes and the equivalent to r+ was identified as
ios_base::in | ios_base::eek:ut. Give it a shot, it works for me. If the
file does not exist, nothing happens. If it exists, it is written to.

Regards,
Rick

#include <fstream>
using namespace std;

int main()
{

ofstream fout;
fout.open("test.txt",ios_base::in | ios_base::eek:ut );
fout << "This is a test." << endl;
fout.close();

}
 
M

Mike Wahler

Dave O'Hearn said:
I think I have to use the hack I found online, where you open for 'in'
mode first, then if it succeeds, reopen for in|out mode. It's odd that
'nocreate' isn't standard, since it's easy enough for a library to
fake even if the OS doesn't support it... and if the library doesn't
fake it, all the user code has to fake it instead. But that didn't
happen, so I will just have to fake it myself, oh well. Thanks.

It appears to me that you're suffering from a broken implementation.
std::ios::in | std::ios::eek:ut should not create the file if it does
not exist. Perhaps consider an upgrade, to a newer version or a
different vendor.

-Mike
 
D

Dave O'Hearn

Mike Wahler said:
It appears to me that you're suffering from a broken implementation.
std::ios::in | std::ios::eek:ut should not create the file if it does
not exist. Perhaps consider an upgrade, to a newer version or a
different vendor.

If I could find a promise to that effect in the Standard, I would hack
around the old platforms and just hope that the behavior goes away
someday. But I can't find anything like it. A search on "openmode"
finds nothing but default parameters in declarations, and one very
terse table describing the 6 openmode flags, with no talk of file
creation. A search on "in|" finds 4 default paramaters in
declarations; a search on "in |" finds nothing. If it's in there
somewhere, I can't find it. It is just not enough for me that, for the
time being, one or two major platforms think the file should not be
created when this happens.
 
R

Rick Noelle

If I could find a promise to that effect in the Standard, I would hack
around the old platforms and just hope that the behavior goes away
someday. But I can't find anything like it. A search on "openmode"
finds nothing but default parameters in declarations, and one very
terse table describing the 6 openmode flags, with no talk of file
creation. A search on "in|" finds 4 default paramaters in
declarations; a search on "in |" finds nothing. If it's in there
somewhere, I can't find it. It is just not enough for me that, for the
time being, one or two major platforms think the file should not be
created when this happens.

Not sure if you saw my earlier post but I found a combination that works
like C's r+ on RedHat 9.0 with gcc 3.2.2. This does not create a file
if it does not exist which if I read correctly, is what you were looking
for. The correct combination is:

fout.open("file.txt",ios_base::in | ios_base::eek:ut );

Also, I mentioned Prata's book and later I noticed this comment in it:

"Compatibility Note:
File I/O was perhaps the least standardized aspect of C++ in its
earlier days, and many older compilers don't quite conform to the
current standard. Some, for example, used modes such as nocreate
that are not part of the current standard."

At any rate, the above fout line works as if you had used nocreate in C on
my system.

Best Regards,
Rick
 
D

Dave O'Hearn

Rick Noelle said:
Not sure if you saw my earlier post but I found a combination that works
like C's r+ on RedHat 9.0 with gcc 3.2.2. This does not create a file
if it does not exist which if I read correctly, is what you were looking
for. The correct combination is:

fout.open("file.txt",ios_base::in | ios_base::eek:ut );

I don't think I need any tricks in Red Hat 9.0. Your trick seems to be
opening an ofstream in in|out mode, even though ofstreams are only
meaningful for writing? I will remember that in case I need it
someday, but in my present application, I definately need fstreams,
because I read and write to the file. Also, Red Hat 9 is not my
problem. The problem is that at least one older platform with gcc 2.x
will create zero-sized files without failing, unless a nonstandard
ios::nocreate flag is used. And unfortunately, the Standard does not
seem to say anything against this, so I am hesitant to blame the
platform for being old. I'm certainly annoyed at the platform, but I'm
not sure I have a right to blame it.
Also, I mentioned Prata's book and later I noticed this comment in it:

"Compatibility Note:
File I/O was perhaps the least standardized aspect of C++ in its
earlier days, and many older compilers don't quite conform to the
current standard. Some, for example, used modes such as nocreate
that are not part of the current standard."

Since posting here, I learned about this old 'nocreate' thing, and
that it isn't standard... but it also doesn't seem to be standard that
openning in|out won't create a zero-sized file instead of failing. So
even if some miracle got rid of gcc 2.x and I didn't have to support
it anymore, who knows what other platforms would still have the same
behavior, and not be in any hurry to change it.

The decision I'm trying to make now is, if even if the Standard
doesn't promise this behavior, maybe all modern platforms give it
anyway, and will keep giving it into the future. If they went that
way, I would feel comfortable hacking around the file opens on the old
platforms, and doing it the simple way on most platforms. I like the
simple way more, as it only opens the files once each, and file opens
can be expensive.
 
D

Dave O'Hearn

Chuck McDevitt said:
You are obviously on Windows. As far as I know, it's implementation
defined if the file gets created or not.
In the Windows implementation it does, on most Unix systems it does not.

Windows has a ios::_Nocreate you can set.

I found out a little more about this. So far as I can tell, you are
right about it being implementation defined to create the file or not.

But it seems that all (or most) classic iostreams implementations
create the file and have some form of ios::nocreate to suppress it,
while all standard iostreams implementations will not create the file
when you open for in|out mode.

This is somewhat more satisfying for me to rely on... "All new
compilers do it one way," was sketchy, but "Really every standard
iostreams implementation does it this way, and really every outdated
classic iostreams implementation does it the other way," makes me feel
comfortable relying on the behavior of the file not being created, and
just saying my application requires standard, not classic, iostreams.

Still I can't find any text in the actual Standard that promises it,
unfortunately.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

fopen 20
How do I open PLINK with R studio 0
std iostreams design question, why not like java stream wrappers? 18
IOStreams 9
fopen() questions 17
fopen - file and directories ?? 15
fopen modes 30
fopen problem 10

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top