How to Pre-Allocate Space for a File in C/C++ on Windows

How do you pre-allocate space for a file in C/C++ on Windows?

Programatically, on Windows you have to use Win32 API functions to do this:

SetFilePointerEx() followed by SetEndOfFile()

You can use these functions to pre-allocate the clusters for the file and avoid fragmentation. This works much more efficiently than pre-writing data to the file. Do this prior to doing your fopen().

If you want to avoid the Win32 API altogether, you can also do it non-programatically using the system() function to issue the following command:

fsutil file createnew filename filesize

Reserve disk space before writing a file for efficiency

void ReserveSpace(LONG spaceLow, LONG spaceHigh, HANDLE hFile)
{
DWORD err = ::SetFilePointer(hFile, spaceLow, &spaceHigh, FILE_BEGIN);

if (err == INVALID_SET_FILE_POINTER) {
err = GetLastError();
// handle error
}
if (!::SetEndOfFile(hFile)) {
err = GetLastError();
// handle error
}
err = ::SetFilePointer(hFile, 0, 0, FILE_BEGIN); // reset
}

Preallocating file space in C#?

FileStream.SetLength is the one you want. The syntax:

public override void SetLength(
long value
)

Pre-allocate disk space for an application

See this answer Reserve disk space before writing a file for efficiency

Qt/C++ (Pre-)Allocating large file

I'm not sure about fragmentation, but Qt has QFile::resize() method which clearly pre-allocates (or truncates) the file. The process is fast - ~1s for 800MB on my machine, therefore the file is clearly not explicitly garbage-filled. Tested on Windows 7.

Creating big file on Windows

Use the Win32 API, CreateFile, SetFilePointerEx, SetEndOfFile, and CloseHandle. In that same order.

The trick is in the SetFilePointerEx function. From MSDN:

Note that it is not an error to set
the file pointer to a position beyond
the end of the file. The size of the
file does not increase until you call
the SetEndOfFile, WriteFile, or
WriteFileEx function.

Windows explorer actually does this same thing when copying a file from one location to another. It does this so that the disk does not need to re-allocate the file for a fragmented disk.

creating a file and allocating storage before writing to it

Using SetLength is a common approach although I'd generally use a using statement here.

using(var fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
fileStream.SetLength((long)fileSizeRequirement);
}

Calling fileStream.Position straight after SetLength yields 0 so you shouldn't need to seek to the beginning.



Related Topics



Leave a reply



Submit