Search code examples
c++file-iofstream

File resize not reflected using std::filebuf


I have created an empty file and I am trying to resize it. My resize and creation code is pretty similar except for the opening mode. The initial creation works as expected. The code for resize executes fine, but the file resize is not reflected.

Here is my code:

void resize()
{
    std::filebuf fileBuffer;
    fileBuffer.open(filePath, ios::out | ios::binary | ios::app);
    if (fileBuffer.is_open())
    {
        fileBuffer.pubseekoff((2 * fileSize) - 1, ios::beg);
        auto x = fileBuffer.sputc(0);
        fileBuffer.close();
    }
}

int main()
{
    std::filebuf fileBuffer;
    fileBuffer.open(filePath, ios::out | ios::trunc | ios::binary);
    if (fileBuffer.is_open())
    {
        fileBuffer.pubseekoff(fileSize - 1, ios::beg);
        fileBuffer.sputc(0);
        fileBuffer.close();
    }
    resize(); // Doesn't work

    resizeWithData(); // Works
}

When I try to resize the file by pushing actual data into it as shown below, it works:

void resizeWithData()
{
    ofstream fstr(filePath, ios::out | ios::binary | ios::app);
    if (fstr.is_open())
    {
        const auto emptySec = make_unique<char[]>(fileSize);
        memset(emptySec.get(), 0, fileSize);
        fstr.write(emptySec.get(), fileSize);
        fstr.close();
    }
}

Why this difference? My actual scenario involves creating and resizing really large files(1 GB and more) and so I was hoping that I could avoid the memory allocation for empty data as shown in the above code(since its really slow) if possible

P.S. : I am working on windows 7 with VS2013 update 4


Solution

  • The reason resize() fails is because you have opened the file in app mode. Every time you write to this stream the implementation will resync the write position to the end of the file. The call to pubseekoff itself, which calls seekoff, which is defined in terms of fseek, doesn't write anything, it just repositions the file position indicator.

    As can be seen in the file you open in main, without the app flag sputc will write immediately to the current position, although this might not be strictly guaranteed.

    Most of the basic_filebuf operations are defined in terms of the C file functions, which don't seem to mention what happens when fputc is called when the file position indicator is beyond the end of the file. POSIX however makes it clear that this will write zeroes up to the position, and you'll probably find that most implementations will support this definition.