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

use*_*191 17 c c++ windows file

我添加一些功能到使用纯C的功能(一个现有的代码库fopen,fwrite,fclose)将数据写入到一个文件.不幸的是我无法改变文件i/o的实际机制,但我必须为文件预先分配空间以避免碎片(这会在读取过程中破坏我们的性能).有没有更好的方法来实际写入零或随机数据到文件?当我打开文件时,我知道文件的最终大小.

我知道我可以在linux上使用fallocate,但我不知道windows的等价物是什么.

谢谢!

Mic*_*eyn 19

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

SetFilePointerEx() followed by SetEndOfFile()
Run Code Online (Sandbox Code Playgroud)

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

如果要完全避免使用Win32 API,还可以使用system()函数以非编程方式执行此操作,以发出以下命令:

fsutil file createnew filename filesize
Run Code Online (Sandbox Code Playgroud)

  • `SetFilePointerEx`后跟`SetEndOfFile`仍然要求将零写入磁盘,除非文件稀疏 - 请参阅[为什么我的单字节写入需要永远?](http://blogs.msdn.com/b/oldnewthing /archive/2011/09/22/10215053.aspx) (2认同)

Ada*_*eld 7

您可以使用该SetFileValidData函数来扩展文件的逻辑长度,而无需将所有数据写入磁盘.但是,因为它可以允许读取您可能没有特权的磁盘数据,所以它需要SE_MANAGE_VOLUME_NAME使用该特权.仔细阅读文档的备注部分.

我建议改为只写出0.您也可以使用SetFilePointerExSetEndOfFile扩展文件,但这样做仍然需要将零写入磁盘(除非该文件很稀疏,但这会使预留磁盘空间失败).请参阅为什么我的单字节写入需要永远?有关更多信息.

  • *您还可以使用 SetFilePointerEx 和 SetEndOfFile 来扩展文件,但这样做仍然需要写出零* - 请注意,只有当您不按顺序写入文件内容时,这才是正确的。如果您从头到尾写入文件,则无需首先显式写出零。 (2认同)

Mar*_*ett 5

示例代码,请注意,它不一定更快,尤其是对于 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);
}
Run Code Online (Sandbox Code Playgroud)