Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

c

file

windows

I'm adding some functionality to an existing code base that uses pure C functions (fopen, fwrite, fclose) to write data out to a file. Unfortunately I can't change the actual mechanism of file i/o, but I have to pre-allocate space for the file to avoid fragmentation (which is killing our performance during reads). Is there a better way to do this than to actually write zeros or random data to the file? I know the ultimate size of the file when I'm opening it.

I know I can use fallocate on linux, but I don't know what the windows equivalent is.

Thanks!

like image 583
user1024191 Avatar asked Nov 01 '11 17:11

user1024191


3 Answers

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
like image 166
Michael Goldshteyn Avatar answered Nov 01 '22 04:11

Michael Goldshteyn


You can use the SetFileValidData function to extend the logical length of a file without having to write out all that data to disk. However, because it can allow to read disk data to which you may not otherwise have been privileged, it requires the SE_MANAGE_VOLUME_NAME privilege to use. Carefully read the Remarks section of the documentation.

I'd recommend instead just writing out the 0's. You can also use SetFilePointerEx and SetEndOfFile to extend the file, but doing so still requires writing out zeros to disk (unless the file is sparse, but that defeats the point of reserving disk space). See Why does my single-byte write take forever? for more info on that.

like image 45
Adam Rosenfield Avatar answered Nov 01 '22 03:11

Adam Rosenfield


Sample code, note that it isn't necessarily faster especially with smart filesystems like NTFS.

if (  INVALID_HANDLE_VALUE != (handle=CreateFile(fileName,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_FLAG_SEQUENTIAL_SCAN,NULL) )) {                                               
        // preallocate 2Gb disk file                
        LARGE_INTEGER size;
        size.QuadPart=2048 * 0x10000;
        ::SetFilePointerEx(handle,size,0,FILE_BEGIN);
        ::SetEndOfFile(handle);
        ::SetFilePointer(handle,0,0,FILE_BEGIN);
}
like image 4
Martin Beckett Avatar answered Nov 01 '22 03:11

Martin Beckett