How can I open a file for reading & writing, creat

2019-01-25 07:02发布

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.

3条回答
smile是对你的礼貌
2楼-- · 2019-01-25 07:16

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`
查看更多
叼着烟拽天下
3楼-- · 2019-01-25 07:16

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.

查看更多
兄弟一词,经得起流年.
4楼-- · 2019-01-25 07:24

Taking std::ios::binary as read, the remaining openmode probably you require is:

std::ios::in | std::ios::app

It's effect is as if to open the file with:

std::fopen(filename,"a+")

and the effect of that is:

  • open or, if it does not exist, create the file for reading and writing
  • write data at the end of the file.

If you open a file as an std::fstream with this openmode, it is not truncated if it exists. You may read from the file wherever the fstream's tellg()\tellp() pointer points, provided there is something there to read, and you can position that pointer with the stream's seekg()\seekp() for reading. However, all writes will be appended to the end of the file.

This openmode will therefore fit your bill unless you need to perform writes into existing data.

查看更多
登录 后发表回答