How can I open a file for reading & writing, creating it if it does not exist, without truncating it?

前端 未结 3 1688
-上瘾入骨i
-上瘾入骨i 2020-12-10 13:00

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 e

相关标签:
3条回答
  • 2020-12-10 13:34

    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`
    
    0 讨论(0)
  • 2020-12-10 13:35

    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.

    0 讨论(0)
  • 2020-12-10 13:37

    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.

    0 讨论(0)
提交回复
热议问题