4

I'm working on some legacy code that uses win32 WriteFile() to write to a random location in a binary file. The offset of the write can be past the end of the file in which case WriteFile() seems to automatically extend the file size to the offset and then write the data to the file.

I'd like to use std::fstream to do the same, but when I try to seekp() to the appropriate location, past the end of the file, the seekp() fails and the subsequent write() fails as well.

So it seems to me that I have to 'manually' fill in the space between the current EOF and the location I want to write to.

The code looks like this:

void Save(size_t offset, const Element& element)
{
    m_File.seekp(offset, std::ios_base::beg);
    m_File.write(reinterpret_cast<const char*>(&element), sizeof(Element));
    if (m_File.fail()) {
        // ... error handling
    }
}

So is my only option to 'manually' write 0s from the current EOF up to offset?

liwp
  • 6,746
  • 1
  • 27
  • 39

1 Answers1

2

Here is an example I picked up verbatim from MSDN:

// basic_ostream_seekp.cpp
// compile with: /EHsc
#include <fstream>
#include <iostream>

int main()
{
    using namespace std;
    ofstream x("basic_ostream_seekp.txt");
    streamoff i = x.tellp();
    cout << i << endl;
    x << "testing";
    i = x.tellp();
    cout << i << endl;
    x.seekp(2);   // Put char in third char position in file
    x << " ";

    x.seekp(2, ios::end);   // Put char two after end of file
    x << "z";
}

The file "basic_ostream_seekp.txt" has te ting\0\0z at the end of the program, i.e., you are allowed to seek past the end of the file.

In any case, if write does fail for you, you could check and see if seekp does too. If it does, you can detect the failure earlier.

user1055604
  • 1,624
  • 11
  • 28
  • Sorry for the late accept - I ended up ditching my std::fstream based code, because the CRT can only allocate upto 2k file handles, and that wasn't enough for us. As for your answer - seeking from ios::end does indeed seem to work. Strange that seeking from ios::beg fails. – liwp May 17 '12 at 13:42
  • I wanted to seek past the end of a file too. I tested with VS 2010 on Windows and some fairly new version of GCC on Linux (our two current platforms), and `ios::beg` worked just as well as `ios::end` [EDIT: though to be absolutely precise, I think I used the one-arg form of `seekp` rather than specifying `ios::beg` explicitly]. Maybe `ios::beg` failed for liwp for some other reason? In my case, the file was open with `ios::in | ios::out | ios::binary`; not sure if that makes a difference. I found frustratingly little actual documentation about the 'past end of file' case. – entheh Mar 27 '13 at 23:47