What is the proper set of I/O flags for a std::fstream
, where I want to be able to read from and write to the file, without truncating the file if it exists, but creating it if it does not?
I've tried
std::ios::binary | std::ios::in | std::ios::out
std::ios::binary | std::ios::in | std::ios::out | std::ios::ate
but neither of these create the file if it does not already exist.
I don't want std::ios::app
, because I also need to be able to seek around the file at will, with both the get and put cursors.
One workaround, I suppose, would be to instantiate an std::ofstream
first, then immediately close it and open the stream I really want, but that seems messy if it can be avoided with a single stream object.
'r+' opens the file for both reading and writing. On Windows, 'b' appended to the mode opens the file in binary mode, so there are also modes like 'rb', 'wb', and 'r+b'. Also reading then writing works equally well using 'r+b' mode, but you have to use f.
To read from a text fileUse the ReadAllText method of the My. Computer. FileSystem object to read the contents of a text file into a string, supplying the path. The following example reads the contents of test.
At this time, I'm concluding that std::ios::in
outright prevents this, and that I must use the workaround.
So:
if (!std::ostream(path.c_str()))
throw std::runtime_error("Could not create/open file");
std::fstream fs(path.c_str(), std::ios::binary | std::ios::in | std::ios::out);
if (!fs)
throw std::runtime_error("Could not open file");
// ... use `fs`
An investigation, from a Linux perspective (though much of this likely applies to other Unices):
At the syscall layer, you want open(O_RDWR | O_CREAT, 0666)
(but not O_TRUNC
or O_APPEND
or a bunch of other flags, though arguably all files should be opened with O_CLOEXEC | O_LARGEFILE
, but that's beside the point)
At the libc layer, there is no standard mode
string that implies O_CREAT
without O_TRUNC
. However, you could use open
followed by fdopen
.
At the C++ library level, there is no standard way to pass the desired flags. However, using implementation-specific classes/functions or third-party libraries, it is possible; see How to construct a c++ fstream from a POSIX file descriptor?
Personally, I tend to do all I/O at the C or even syscall level, since the API is a lot nicer and it's more predictable. For input/output of class instances, I have my own templates.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With