如何在Windows上为C / C ++中的文件预分配空间?

我将一些function添加到使用纯C函数( fopenfwritefclose )将数据写入文件的现有代码库中。 不幸的是,我不能改变文件I / O的实际机制,但我必须为文件预先分配空间以避免碎片化(这会在读取期间破坏我们的性能)。 有没有更好的方法来做到这一点,而不是实际写零或随机数据的文件? 当我打开文件时,我知道文件的最终大小。

我知道我可以在Linux上使用fallocate,但我不知道什么是Windows的等价物。

谢谢!

Solutions Collecting From Web of "如何在Windows上为C / C ++中的文件预分配空间?"

以编程方式,在Windows上,您必须使用Win32 API函数来执行此操作:

 SetFilePointerEx() followed by SetEndOfFile() 

您可以使用这些功能为文件预先分配群集,并避免碎片。 这比将数据预写入文件更有效。 做这个之前做你的fopen()

如果您想完全避免使用Win32 API,也可以使用system()函数以非编程方式执行以下命令:

 fsutil file createnew filename filesize 

您可以使用SetFileValidData函数来扩展文件的逻辑长度,而不必将所有数据写出到磁盘。 但是,因为它可以允许读取您可能没有权限的磁盘数据,所以需要使用SE_MANAGE_VOLUME_NAME权限。 仔细阅读文档的“ 备注”部分。

我建议,而不是写出0的。 您也可以使用SetFilePointerExSetEndOfFile来扩展文件,但是这样做仍然需要向磁盘写入零(除非文件稀疏,但是这会破坏预留磁盘空间的点)。 请参阅为什么我的单字节写入永远? 欲了解更多信息。

示例代码,请注意,它不一定更快,尤其是像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); } 

你可以使用_chsize()函数。

在Code Project上看看这个例子。 当文件初始化时,设置文件的大小看起来相当简单。

http://www.codeproject.com/Questions/172979/How-to-create-a-fixed-size-file.aspx

 FILE *fp = fopen("C:\\myimage.jpg","ab"); fseek(fp,0,SEEK_END); long size = ftell(fp); char *buffer = (char*)calloc(500*1024-size,1); fwrite(buffer,500*1024-size,1,fp); fclose(fp);