How to choose open mode with fopen()?
Solution 1
You will have to deal with the possibly non-existent file in two stages, first assuming that it is there and then dealing with its absence:
if ((f = fopen(filename, "rb+") == 0)
f = fopen(filename, "wb+");
if (f == 0)
...report error...
The "rb+"
mode will fail to open a non-existent file (but otherwise behaves as you want). If the file doesn't exist, then "wb+"
will do what you want instead (though it could still fail, for example if the file exists but you don't have permission to write to it). You have to hope that you've not been subjected to a TOCTOU (Time of Check, Time of Use) attack with the double attempt.
An alternative approach uses the 3-argument version of the open()
system call with appropriate flags to open a file descriptor, and then uses fdopen()
to create a file stream from the file descriptor:
#include <fcntl.h>
int fd;
if ((fd = open(filename, O_RDRW | O_CREAT, 0644)) >= 0)
f = fdopen(fd, "rb+");
You get rather precise control over open()
with the flags.
Solution 2
The file modes are clearly documented for fopen
(try man 3 fopen
on Unix/Linux/OS X).
r+
Open for reading and writing. The stream is positioned at the beginning of the file.
Summer_More_More_Tea
Updated on June 29, 2022Comments
-
Summer_More_More_Tea almost 2 years
I have a problem about file open mode with
fopen()
.In my case, I want to seek the cursor freely, may be even beyond
EOF
sometimes. What's more, I also want to append to it instead of truncating the existing file. I tried to open the file ina+
mode; however, I cannot seek file cursor freely. Each time I seek the cursor beyondEOF
, new arrival data will be append to end of the file, not the position I specified. While, if open inw+
mode, the existing file will be truncated. Is there a perfect solution to this problem?
UPDATE:
One point not clearly specified is that the file may not always exist; I have to create a new file in that case.
In fact, I want to process a configuration file. I don't know whether it is good practice to implement like this. Or should I first place an empty configuration file. Thus there is no need to care about the case file does not exist?
Below is the code snippet:
FILE *f = fopen(FILE_PATH, "wb+"); struct record r; if (f) { if (fread((void *)&r, 1, sizeof(struct record), f) { /* File exists, do the normal flow */ } else { if (feof(f)) { /* File is newly created, do some initialization */ } } } else { /* issue a warning */ }