How can ofstream not trunc existing file?

Hi,

I have this code that erases the output file as it opens it... I want to not truncate the file.

1
2
3
4
5
6
7
ofstream os{ to };
ostream_iterator<string> oo{ os, "\n" };	// output iterator for stream

vector<string> b{ ii,eos };	// b is a vector initialized from input
sort(b.begin(), b.end());

unique_copy(b.begin(), b.end(), oo);



If we do not want to seek to the end of stream before each write (ie. we do not want std::ios_base::app behaviour):
1
2
3
4
5
6
7
8
9
10
#include <fstream>
#include <filesystem>

std::ofstream open_no_trunc( const char* path )
{
    if( std::filesystem::exists(path) )
        return std::ofstream( path, std::ios::in|std::ios::out ) ; // try to open existing file
    else // file does not exist; try to create it
        return std::ofstream(path) ;
}
I think the "problem" with the above code is that is not atomic.

For example, the file might be created in the time between std::filesystem::exists() check and the std::ofstream() constructor.

If platform-specific code is allowed, you can do this to create/open the file in an atomic way (MSVC):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#include <fstream>

std::ofstream open_no_trunc(const wchar_t *const path)
{
    const int fd = _wopen(path, _O_RDWR | _O_BINARY | _O_CREAT, _S_IREAD | _S_IWRITE);
    if (fd == -1)
    {
        throw "Failed to open file!";
    }

    FILE *const file = _fdopen(fd, "w+b");
    if (!file)
    {
        throw "Something went wrong!";
    }

    return std::ofstream(file);
}

Note:
_O_CREAT
Creates a file and opens it for writing. Has no effect if the file specified by filename exists.
Last edited on
Topic archived. No new replies allowed.